digitalmars.D - Free functions versus member functions
- Walter Bright <newshound1 digitalmars.com> Oct 10 2007
- Bill Baxter <dnewsgroup billbaxter.com> Oct 10 2007
- Walter Bright <newshound1 digitalmars.com> Oct 10 2007
- "Kris" <foo bar.com> Oct 10 2007
- Walter Bright <newshound1 digitalmars.com> Oct 10 2007
- janderson <askme me.com> Oct 10 2007
- "Kris" <foo bar.com> Oct 10 2007
- Regan Heath <regan netmail.co.nz> Oct 11 2007
- Chad J <gamerChad _spamIsBad_gmail.com> Oct 11 2007
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Oct 11 2007
- Bill Baxter <dnewsgroup billbaxter.com> Oct 11 2007
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= <jmjmak utu.fi.invalid> Oct 11 2007
- BCS <ao pathlink.com> Oct 11 2007
- Bill Baxter <dnewsgroup billbaxter.com> Oct 11 2007
- Kevin Bealer <kevinbealer gmail.com> Oct 10 2007
- janderson <askme me.com> Oct 11 2007
- Bruno Medeiros <brunodomedeiros+spam com.gmail> Oct 13 2007
Continuing the discussion from the thread "questions on PhanTango 'merger'": Lars Ivar Igesund wrote:It is not as if such functions are non-existant in Tango, so which exact functionality do you think is better expressed through free standing functions rather than objects? The answers of others shows that this usually is wanted for objects where you often need only one operation on the given object, even if others are available. This don't remove the
that an object (class) equally often is a useful abstraction, and
is established, free standing functions usually should be implemented as wrappers around each method on the object, rather than the object being implemented via free standing functions. This is why Tango looks as
today; we have avoided wrappers of our own code if possible, because they degrade orthogonality of the API, and add more code to maintain.
have been to strict in enforcing that stance, is an open question.
I've been stumped by this design issue before. Should functionality be done as a set of free functions, or as member functions? I remember going over this with Matthew Wilson, and he resolved it by implementing two parallel sets of interfaces: one free, the other member. I thought that doing both was a copout, but couldn't figure out which one was right. I eventually ran across this article by Scott Meyers http://www.ddj.com/cpp/184401197 which made a lot of sense. It gives some good guidelines to use to make such decisions, and backs it up with reasoning that I find compelling. Isn't it funny how we've completed the circle? We went from all free functions in C, to all member functions in C++, and now back to free functions? <g>
Oct 10 2007
Walter Bright wrote:Continuing the discussion from the thread "questions on PhanTango 'merger'": Lars Ivar Igesund wrote: > It is not as if such functions are non-existant in Tango, so which exact > functionality do you think is better expressed through free standing > functions rather than objects? The answers of others shows that this > usually is wanted for objects where you often need only one operation on > the given object, even if others are available. This don't remove the fact > that an object (class) equally often is a useful abstraction, and when that > is established, free standing functions usually should be implemented as > wrappers around each method on the object, rather than the object being > implemented via free standing functions. This is why Tango looks as it does > today; we have avoided wrappers of our own code if possible, because they > degrade orthogonality of the API, and add more code to maintain. Whether we > have been to strict in enforcing that stance, is an open question. I've been stumped by this design issue before. Should functionality be done as a set of free functions, or as member functions? I remember going over this with Matthew Wilson, and he resolved it by implementing two parallel sets of interfaces: one free, the other member. I thought that doing both was a copout, but couldn't figure out which one was right. I eventually ran across this article by Scott Meyers http://www.ddj.com/cpp/184401197 which made a lot of sense. It gives some good guidelines to use to make such decisions, and backs it up with reasoning that I find compelling. Isn't it funny how we've completed the circle? We went from all free functions in C, to all member functions in C++, and now back to free functions? <g>
From the fine article: """ Herb Sutter has explained that the "interface" to a class (roughly speaking, the functionality provided by the class) includes the non-member functions related to the class, and he's shown that the name lookup rules of C++ support this meaning of "interface" [7,8]. """ Do D's name lookup rules similarly support that meaning of "interface"? (I'm not sure what the Herb was talking about but I'm guessing he meant things like preferring the most-derived type for overloads and argument dependent lookup.) --bb
Oct 10 2007
Bill Baxter wrote:From the fine article: """ Herb Sutter has explained that the "interface" to a class (roughly speaking, the functionality provided by the class) includes the non-member functions related to the class, and he's shown that the name lookup rules of C++ support this meaning of "interface" [7,8]. """ Do D's name lookup rules similarly support that meaning of "interface"? (I'm not sure what the Herb was talking about but I'm guessing he meant things like preferring the most-derived type for overloads and argument dependent lookup.)
I think Herb was talking about ADL. D doesn't have ADL, but the next update will include "overload sets" which, although very different, accomplish the same thing.
Oct 10 2007
"Walter Bright" <newshound1 digitalmars.com>I think Herb was talking about ADL. D doesn't have ADL, but the next update will include "overload sets" which, although very different, accomplish the same thing.
Does D + ADL == ADD ? :p
Oct 10 2007
Kris wrote:"Walter Bright" <newshound1 digitalmars.com>I think Herb was talking about ADL. D doesn't have ADL, but the next update will include "overload sets" which, although very different, accomplish the same thing.
Does D + ADL == ADD ? :p
Nope. O.D.D.
Oct 10 2007
Walter Bright wrote:Continuing the discussion from the thread "questions on PhanTango 'merger'": Lars Ivar Igesund wrote: > It is not as if such functions are non-existant in Tango, so which exact > functionality do you think is better expressed through free standing > functions rather than objects? The answers of others shows that this > usually is wanted for objects where you often need only one operation on > the given object, even if others are available. This don't remove the fact > that an object (class) equally often is a useful abstraction, and when that > is established, free standing functions usually should be implemented as > wrappers around each method on the object, rather than the object being > implemented via free standing functions. This is why Tango looks as it does > today; we have avoided wrappers of our own code if possible, because they > degrade orthogonality of the API, and add more code to maintain. Whether we > have been to strict in enforcing that stance, is an open question. I've been stumped by this design issue before. Should functionality be done as a set of free functions, or as member functions? I remember going over this with Matthew Wilson, and he resolved it by implementing two parallel sets of interfaces: one free, the other member. I thought that doing both was a copout, but couldn't figure out which one was right. I eventually ran across this article by Scott Meyers http://www.ddj.com/cpp/184401197 which made a lot of sense. It gives some good guidelines to use to make such decisions, and backs it up with reasoning that I find compelling. Isn't it funny how we've completed the circle? We went from all free functions in C, to all member functions in C++, and now back to free functions? <g>
I'm sure you Walter have read these but for anyone else: I like this interview with Bjarne Stroustrup. I think it explains it reasonably well. http://www.artima.com/intv/goldilocks3.html Also Hurb Sutters book "C++ Coding Standards" as a good explanation: http://www.gotw.ca/publications/c++cs.htm Its actually the official "coding style guide" where I work. -Joel
Oct 10 2007
Yes, that perspective resonates, though I tend to use the term 'client functions' to describe what Scott is calling non-member functions. There's some specific interest here with regard to D: 1) the Widget factory example is less clear in D, due to that lack of an equivalent 'namespace' mechanism. This is why such methods tend to reside inside the respective class/struct in D. Yes, one could perhaps use "import as" instead, but that would tend to muddy usage further. I think this indicates a minor annoyance with the D namespace mechanism. One that's bothered me from time to time <g> 2) the section on "syntax issues" is something that D, on the other hand, is fairly adept at: the support for "flip that outside left-hand reference into the first argument instead", which people got excited about regarding arrays, does help to maintain syntactic symmetry. That's assuming you can avoid namespace collisions in the process. As I understand it, some of the changes in D v2 are intended to address that latter concern? The interesting thing overall is this: what Scott describes has minimal bearing on the concerns within Tango, since we've mostly been attuned to the client/member issue from the beginning. Where we do currently deviate, it is due to concerns over #1 above. Having said that, and assuming I correctly understand some of the comments made about Tango (over the last year), perhaps Tango just doesn't have sufficient 'client' functions? "Walter Bright" <newshound1 digitalmars.com> wrote in message news:feju2r$1nsn$1 digitalmars.com...Continuing the discussion from the thread "questions on PhanTango 'merger'": Lars Ivar Igesund wrote:It is not as if such functions are non-existant in Tango, so which exact functionality do you think is better expressed through free standing functions rather than objects? The answers of others shows that this usually is wanted for objects where you often need only one operation on the given object, even if others are available. This don't remove the
that an object (class) equally often is a useful abstraction, and
is established, free standing functions usually should be implemented as wrappers around each method on the object, rather than the object being implemented via free standing functions. This is why Tango looks as
today; we have avoided wrappers of our own code if possible, because they degrade orthogonality of the API, and add more code to maintain.
have been to strict in enforcing that stance, is an open question.
I've been stumped by this design issue before. Should functionality be done as a set of free functions, or as member functions? I remember going over this with Matthew Wilson, and he resolved it by implementing two parallel sets of interfaces: one free, the other member. I thought that doing both was a copout, but couldn't figure out which one was right. I eventually ran across this article by Scott Meyers http://www.ddj.com/cpp/184401197 which made a lot of sense. It gives some good guidelines to use to make such decisions, and backs it up with reasoning that I find compelling. Isn't it funny how we've completed the circle? We went from all free functions in C, to all member functions in C++, and now back to free functions? <g>
Oct 10 2007
Kris wrote:Yes, that perspective resonates, though I tend to use the term 'client functions' to describe what Scott is calling non-member functions. There's some specific interest here with regard to D: 1) the Widget factory example is less clear in D, due to that lack of an equivalent 'namespace' mechanism. This is why such methods tend to reside inside the respective class/struct in D. Yes, one could perhaps use "import as" instead, but that would tend to muddy usage further. I think this indicates a minor annoyance with the D namespace mechanism. One that's bothered me from time to time <g>
What about D's modules or packages, aren't they the equivalent of a namespace? If not, what do they lack? Regan
Oct 11 2007
Regan Heath wrote:What about D's modules or packages, aren't they the equivalent of a namespace? If not, what do they lack? Regan
I'm not sure about namespaces, but one thing that putting stuff in structs/classes does is it forces users to state where the functions/data they are using comes from. It's forced FQN (Fully Qualified Name) syntax in a sense. It is nicer than just using module-based FQN because Stdout.formatln() is shorter than tango.io.Stdout.formatln() and still gets the point across. It would be nice to be able to write stdio.writefln(), which wouldn't lose much since it is very unlikely that there will be a series of imports like so: std.stdio; somelib.stdio; somelib.subpackage.stdio; In above such cases, well, too bad. Someone trying to figure out where stdio.writefln came from will just have to look it up. I may have just conflated two things unfortunately: compulsory FQN vs. voluntary FQN is one, and the other is the notion of a partially qualified name (PQN?). Currently D modules are voluntary FQN, while structs/classes act as compulsory PQN. Another thing that makes me tend to throw things into structs and classes is that private-is-visible. Consider this: //main.d import std.stdio; import primary; import secondary; void main() { writefln( generate() ); } // primary.d public char[] generate() { return "Hello from primary!"; } // secondary.d private char[] generate() { return "Hell from secondary!"; } Compiling the above code results in the following error: main.d(7): Error: primary.generate at primary.d(2) conflicts with secondary.generate at secondary.d(2) When I declare something private, I generally don't want it to affect anything in other modules, at all. Other modules do get affected in D, in the form of compiler errors, but a similar effect can be gained by just throwing things into structs or classes. This has been discussed before. I remember Walter liking it this way. It was to allow people to "poison" certain function overloads. It's a small thing, but annoying.
Oct 11 2007
"Chad J" <gamerChad _spamIsBad_gmail.com> wrote in message news:fel0ol$tnn$1 digitalmars.com...It would be nice to be able to write stdio.writefln(), which wouldn't lose much since it is very unlikely that there will be a series of imports like so: std.stdio; somelib.stdio; somelib.subpackage.stdio; In above such cases, well, too bad. Someone trying to figure out where stdio.writefln came from will just have to look it up. I may have just conflated two things unfortunately: compulsory FQN vs. voluntary FQN is one, and the other is the notion of a partially qualified name (PQN?). Currently D modules are voluntary FQN, while structs/classes act as compulsory PQN.
You might already know about this, but D already has a way to force the use of module-level FQNs and a way to rename modules when importing them: static import foo; // all members have to be accessed as foo.* import stdio1 = somelib.stdio; import stdio2 = somelib.subpackage.stdio; // Now you can access stdio1.* and stdio2.* The only somewhat annoyting part about this is that you have to do something _at import time_, something whith can't be enforced by the library that's being imported. I think it might be nicer if you could, at the very least, declare a module itself as static (static module foo; for the above example), and when you import it, it's automatically a static import.
Oct 11 2007
Regan Heath wrote:Kris wrote:Yes, that perspective resonates, though I tend to use the term 'client functions' to describe what Scott is calling non-member functions. There's some specific interest here with regard to D: 1) the Widget factory example is less clear in D, due to that lack of an equivalent 'namespace' mechanism. This is why such methods tend to reside inside the respective class/struct in D. Yes, one could perhaps use "import as" instead, but that would tend to muddy usage further. I think this indicates a minor annoyance with the D namespace mechanism. One that's bothered me from time to time <g>
What about D's modules or packages, aren't they the equivalent of a namespace? If not, what do they lack?
Two big differences with D's modules and C++ namespaces 1) A single C source file can have any number of (possibly nested) namespaces 2) A single namespace can be split across parts of lots of files The result is that C++ namespaces are usually used to represent bigger collections of functionality. Like "IO" or "Net". Not IO.Conduit.BufferedNosePicker They're used more for package-level scoping than module-level. I don't think I have ever seen C++ code that uses a 1-file per 1-namespace mapping. You certainly could do that with C++, but there is just no reason to. Another difference is that in C++ you have to *explicitly* say you want to bring members of a namespace into your current namespace with a "using" directive. In contrast, D's imports throw all the symbols into the local namespace by default. You have to do something extra to prevent it ("static import" instead of import). "Using" is also a nice tool for manipulating visibility of namespaces. D doesn't have anything quite like it. You can say at the function level for instance "using SomeNamespace" and then you can use things from that namespace unqualified, but just to the end of that function. There's also a renamed using -- something like "using SNS = SomeNamespace;" I think. --bb
Oct 11 2007
Bill Baxter wrote:Another difference is that in C++ you have to *explicitly* say you want to bring members of a namespace into your current namespace with a "using" directive. In contrast, D's imports throw all the symbols into the local namespace by default. You have to do something extra to prevent it ("static import" instead of import).
I haven't been using C++ lately, but isn't 'using namespace' similar to D import - it imports all symbols from the namespace. Explicit syntax is nameSpace::symbol IIRC."Using" is also a nice tool for manipulating visibility of namespaces. D doesn't have anything quite like it. You can say at the function level for instance "using SomeNamespace" and then you can use things from that namespace unqualified, but just to the end of that function. There's also a renamed using -- something like "using SNS = SomeNamespace;" I think.
Well isn't this what has been proposed for D already, i.e. imports inside non-module level scopes.
Oct 11 2007
Reply to Jari-Matti Mäkelä,Bill Baxter wrote:Another difference is that in C++ you have to *explicitly* say you want to bring members of a namespace into your current namespace with a "using" directive. In contrast, D's imports throw all the symbols into the local namespace by default. You have to do something extra to prevent it ("static import" instead of import).
to D import - it imports all symbols from the namespace. Explicit syntax is nameSpace::symbol IIRC.
without an import. In C++ you can access it, but you need the FQN if you don't use using.
Oct 11 2007
BCS wrote:Reply to Jari-Matti Mäkelä,Bill Baxter wrote:Another difference is that in C++ you have to *explicitly* say you want to bring members of a namespace into your current namespace with a "using" directive. In contrast, D's imports throw all the symbols into the local namespace by default. You have to do something extra to prevent it ("static import" instead of import).
to D import - it imports all symbols from the namespace. Explicit syntax is nameSpace::symbol IIRC.
without an import. In C++ you can access it, but you need the FQN if you don't use using.
Well, yes. But in C++ you still need #include the definition some way first. The only difference is C++ and D have different kinds of mappings between namespaces and files. I guess you could get similar behavior by also extending import to import subscopes inside a module.
Oct 11 2007
Jari-Matti Mäkelä wrote:Bill Baxter wrote:Another difference is that in C++ you have to *explicitly* say you want to bring members of a namespace into your current namespace with a "using" directive. In contrast, D's imports throw all the symbols into the local namespace by default. You have to do something extra to prevent it ("static import" instead of import).
I haven't been using C++ lately, but isn't 'using namespace' similar to D import - it imports all symbols from the namespace. Explicit syntax is nameSpace::symbol IIRC."Using" is also a nice tool for manipulating visibility of namespaces. D doesn't have anything quite like it. You can say at the function level for instance "using SomeNamespace" and then you can use things from that namespace unqualified, but just to the end of that function. There's also a renamed using -- something like "using SNS = SomeNamespace;" I think.
Well isn't this what has been proposed for D already, i.e. imports inside non-module level scopes.
Maybe, assuming the imports could be repeats of already imported modules. But anyway, proposed and implemented are very different things. People have also proposed that D compilers should be able compile C++ code directly. --bb
Oct 11 2007
Walter Bright Wrote:Continuing the discussion from the thread "questions on PhanTango 'merger'": Lars Ivar Igesund wrote: > It is not as if such functions are non-existant in Tango, so which exact > functionality do you think is better expressed through free standing > functions rather than objects? The answers of others shows that this > usually is wanted for objects where you often need only one operation on > the given object, even if others are available. This don't remove the fact > that an object (class) equally often is a useful abstraction, and when that > is established, free standing functions usually should be implemented as > wrappers around each method on the object, rather than the object being > implemented via free standing functions. This is why Tango looks as it does > today; we have avoided wrappers of our own code if possible, because they > degrade orthogonality of the API, and add more code to maintain. Whether we > have been to strict in enforcing that stance, is an open question. I've been stumped by this design issue before. Should functionality be done as a set of free functions, or as member functions? I remember going over this with Matthew Wilson, and he resolved it by implementing two parallel sets of interfaces: one free, the other member. I thought that doing both was a copout, but couldn't figure out which one was right. I eventually ran across this article by Scott Meyers http://www.ddj.com/cpp/184401197 which made a lot of sense. It gives some good guidelines to use to make such decisions, and backs it up with reasoning that I find compelling. Isn't it funny how we've completed the circle? We went from all free functions in C, to all member functions in C++, and now back to free functions? <g>
I like Meyer's point here. My view is that classes provide the following added value: they let you define a bunch of operations without defining how they specifically will work. The example I think of is what I believe are two mistakes in the C++ STL, the first is 'sort'. I think it "should" be a member function, as vector::sort and list::sort have to be done differently for efficiency reasons. They give us the efficiency by making list::sort a member and vector can be sorted with sort(v.begin(), v.end()). But I think that's a mistake, since you can't write a good template that calls x.sort() and expect it to do the best thing. The other mistake (I think) is in the other direction, which is the 'extra' members that classes like string and vector have that give them personalities. For example, methods like "push_back()" and "rfind()" could be implemented externally for both string and vector, and it would result in less complexity AND more capability. (Maybe they wanted something like Boyer-Moore for string's find() related code?) Kevin
Oct 10 2007
Kevin Bealer wrote:Walter Bright Wrote:I eventually ran across this article by Scott Meyers
which made a lot of sense. It gives some good guidelines to use to
Isn't it funny how we've completed the circle? We went from all free
functions? <g>I like Meyer's point here. My view is that classes provide the following added value: they let you define a bunch of operations without defining how they specifically will work. The example I think of is what I believe are two mistakes in the C++ STL, the first is 'sort'. I think it "should" be a member function, as vector::sort and list::sort have to be done differently for efficiency reasons.
I've found sort as a non-member function quite useful when I needed to change the code from a std::vector to a standard C array. A nice thing about non-member functions is they can work with privative types too.
They give us the efficiency by making list::sort a member and vector can be sorted with sort(v.begin(), v.end()). But I think that's a mistake, since you can't write a good template that calls x.sort() and expect it to do the best thing.
I'm not sure what you what you are getting at here. I don't think a member function list::sort was a good idea.The other mistake (I think) is in the other direction, which is the
personalities. For example, methods like "push_back()" and "rfind()" could be implemented externally for both string and vector, and it would result in less complexity AND more capability. (Maybe they wanted something like Boyer-Moore for string's find() related code?)Kevin
Perhaps these could be external however it would probably restrict optimizations and verifications that can be applied to these (without exposing more of the class then you need too). However it does seem odd to have find functions in 2 different places and my pet peeve with STL is that it has low discover-ability. -Joel
Oct 11 2007
Walter Bright wrote:Continuing the discussion from the thread "questions on PhanTango 'merger'": I've been stumped by this design issue before. Should functionality be done as a set of free functions, or as member functions? I remember going over this with Matthew Wilson, and he resolved it by implementing two parallel sets of interfaces: one free, the other member. I thought that doing both was a copout, but couldn't figure out which one was right. I eventually ran across this article by Scott Meyers http://www.ddj.com/cpp/184401197 which made a lot of sense. It gives some good guidelines to use to make such decisions, and backs it up with reasoning that I find compelling. Isn't it funny how we've completed the circle? We went from all free functions in C, to all member functions in C++, and now back to free functions? <g>
I don't think I fully agree with some points of that article. He states that a function that can be implemented as a "non-friend non-member" function instead of a member function, should be implemented that way, since it would reduce encapsulation. Well, sorta. Just because a function is written as a member function doesn't mean we have to access the classes fields directly in that function, one can use the class's external API just as if the function was non-member, and thus have no decrease in encapsulation. Second, I think that many times it is useful to have as part of the class API certain utility functions (that are not part of the minimal set and as such could be implemented as free functions), simply because they would be commonly useful. He mentions this aspect in the end of the article, but he gives the impression that he thinks including such functions is only worthwhile in rare occasions, and that classes should always have the minimal set of members, or close to it. I on the other hand think that most functions that could be expected to be used often should be part of the API. For instance, consider the IPath class of Eclipse: http://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/core/runtime/IPath.html It's a class that represents a path name: a collections of path segments plus a device id. I think that class API/interface is ideally defined in terms of number of member functions, but according to Meyers, the class should have a lot less member functions. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Oct 13 2007
API building can sometimes lead to classes that have methods quite unrelated to what the objects are intended for, just because we need some utility functions to be used with them. Traits (as in http://www.iam.unibe.ch/~scg/Research/Traits/) have been suggested to address this problem. From what I understood we could use mixin template class to add utility behaviour to a class ,in D. This would allow us to keep a minimalistic set of members in a class and create new ones with reusable units of utility behaviour. This also leads to simpler inheritance hierarchies. Here is what it could look like: interface SomeConstraints { // define some methods/properties requires for the trait to work } class Behaviour ( T : SomeConstraints ): T { // a traits is a stateless set of reusable methods and should only have methods. void extendedOperation (); } class Basic : SomeConstraints { // methods ; } void main () { Basic polymorphicBasic = new Behaviour !( Basic )( args, ... ); polymorphicBasic.extendedOperation (); } Currently constructors are not inherited (unless I am not up to date) and adding behaviours using this kind of code would not be easy without default constructors. Bruno Medeiros Wrote:Walter Bright wrote:Continuing the discussion from the thread "questions on PhanTango 'merger'": I've been stumped by this design issue before. Should functionality be done as a set of free functions, or as member functions? I remember going over this with Matthew Wilson, and he resolved it by implementing two parallel sets of interfaces: one free, the other member. I thought that doing both was a copout, but couldn't figure out which one was right. I eventually ran across this article by Scott Meyers http://www.ddj.com/cpp/184401197 which made a lot of sense. It gives some good guidelines to use to make such decisions, and backs it up with reasoning that I find compelling. Isn't it funny how we've completed the circle? We went from all free functions in C, to all member functions in C++, and now back to free functions? <g>
I don't think I fully agree with some points of that article. He states that a function that can be implemented as a "non-friend non-member" function instead of a member function, should be implemented that way, since it would reduce encapsulation. Well, sorta. Just because a function is written as a member function doesn't mean we have to access the classes fields directly in that function, one can use the class's external API just as if the function was non-member, and thus have no decrease in encapsulation. Second, I think that many times it is useful to have as part of the class API certain utility functions (that are not part of the minimal set and as such could be implemented as free functions), simply because they would be commonly useful. He mentions this aspect in the end of the article, but he gives the impression that he thinks including such functions is only worthwhile in rare occasions, and that classes should always have the minimal set of members, or close to it. I on the other hand think that most functions that could be expected to be used often should be part of the API. For instance, consider the IPath class of Eclipse: http://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/core/runtime/IPath.html It's a class that represents a path name: a collections of path segments plus a device id. I think that class API/interface is ideally defined in terms of number of member functions, but according to Meyers, the class should have a lot less member functions. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Oct 13 2007









Walter Bright <newshound1 digitalmars.com> 