Re: Private library symbols...
On 18 Oct 2006, at 01:10, Sheldon Gill wrote: Well, you actually are relying on conventions anyway. You've called the class _GSPrivate using the underscore convention to indicate privacy. Sure ... as I said, I used a variety of mechanisms ... to be as safe as possible. Also, these are private function calls within the library. Encapsulation doesn't really apply here. I don't see why you say that ... encapsulation is a principle to enhance maintainability which applies at various levels. It breaks large problems down into smaller ones and you need to get very small indeed before it's unimportant. Conventional layout has private functions near the top of the source file, just after header includes. They aren't that hard to find. Especially if you keep to convention with the underscores. I think this statement is a good point in support of trying to use language features in addition to conventions ... since your notion of 'conventional layout' is by no means universal. I'm not even sure that putting private functions 'near the top' is conventional at all other than in as much as you need to declare something before you use it. Many people prefer to put declarations as close as possible to the place they are first used. I'm all in favour of using conventions to aid maintainability ... but I don't believe in relying on a single convention (which may not be universal) when other mechanisms can be used too. As to the leading underscore, that is used by C and Objective-C and extensively within -core. Who is going to be working with the code who doesn't know the language? Are you advocating that we change the way -core is written so that its easy for those not familiar with the language? That we should eschew idiom and use different approaches to facilitate that? No, I'm talking about working *with* those conventions and enhancing them ... and making things work with the Objective-C idioms more than the C idioms. And what is the real problem with the global symbols? Are you suggesting that people look through the library symbol table and choose methods/functions based on what they find there? That certainly happens with proprietory code ... and while I see no good reason for people to do that with open source code, I expect that they will apply the habits/techniques they have developed when working with other systems when they come to program with GNUstep. And that it is an issue for -core maintainers to address? Sure ... not a big issue, but why not take account of it. What would be involved in this? If we *can* remove symbols effectively without breaking the library's internal use of them or impairing debugging, it would probably be good to do so. Try: $ strip I can't find any option in the manual for strip to selectively remove information so that some functions can't be linked to ... and removing all symbol information would certainly impair debugging. Am I missing something obvious? Just to be clear, I'm all for improving the code for reading, navigation and maintenance. I simply disagree that this class wrapping is the right way to do it. We can achieve all those goals without the class wrapper. Yes ...but a class wrapper is a natural way to do it for ObjC programmers ... really the only reason for doing it that way rather than functions in a dispatch table for instance (which would achieve all the other objectives). ___ Gnustep-dev mailing list Gnustep-dev@gnu.org http://lists.gnu.org/mailman/listinfo/gnustep-dev
Re: Private library symbols...
On 18 Oct 2006, at 11:46, Matt Rice wrote: this can also be done by using the __attribute__ ((visibility (hidden))) function attribute found in the gcc info page.. requires gcc 3.something and not available on all platforms, but,put putting a define in there such as #define GS_HIDDEN for those platforms should deter usage because of the threat that most platforms used wont link coupled with the fact that the functions are not declared in any installed header files.. That's great ... exactly the sort of thing I've been looking for! I checked various versions of the gcc documentation online, and it looks like this was introduced at 3.3 and is still present in 4.1 i haven't really looked into whats been done, but find the definition of private a little ambiguous wrt scope e.g. private methods/functions for a classes internal usage i like to keep these as static functions... Yes ... functions only used within a single file should always be static. I think private methods should be declared in a private category and use an underscore prefix (and be kept to a minimum). private methods/functions to be used by other classes in the same library, This is the case that the visibility attribute is perfect for (functions), and I suppose private methods should use the same conventions as those for internal use within a single file ... the only difference would be that the files inside the library need to share a common header to declare the library-private categories. I've put GSPrivate.h in base/Source for this. private methods to be used between libraries like the gui/back backend stuff.. I'm not sure we should consider gui/back interaction private ... I think we actually want a public API for this, which people can use to implement otyher backends. all which imho warrant different solutions... anyhow, toss me in the 'prefers private functions' boat Well, your suggestion of the visibility attribute removes my biggest reason for using methods rather than functions. I think remaining reasons are rather a matter of taste ... do we want to use ObjC semantics or C semantics generally? Do we care whether we group functionality in a class, or use a collection of functions with a common prefix? Do we want to use a single style or both functions and methods? My personal preference (but it's not a strong one) would be to group functionality in classes rather than have a lot of methods anyway, but to use private (ie visibility hidden) functions where there might be a performance issue. ___ Gnustep-dev mailing list Gnustep-dev@gnu.org http://lists.gnu.org/mailman/listinfo/gnustep-dev
Re: Private library symbols...
I think remaining reasons are rather a matter of taste ... do we want to use ObjC semantics or C semantics generally? Do we care whether we group functionality in a class, or use a collection of functions with a common prefix? Do we want to use a single style or both functions and methods? [I'll just chip in, drop my comments, and walk out. Feel free to do what you want with them ;-)] If the functions act on the same data then they should be methods of the same object (the data becomes the instance, and the functions become the methods). :-) If the functions are unrelated pieces of code, or even loosely related pieces of code that don't share data, then it would make sense to leave them as separate functions. :-) You can still group them in the same file. Generally, using higher-level semantics (like objects and methods) where they are not needed adds complexity. Functions are really easy to understand. A last comment is that you can't hide a method no matter how hard you try -- it will always be possible to retrieve it from the ObjC runtime. ;-) So in terms of making things really private, a function appropriately setup to be not visible outside the library seems the perfect solution. ;-) Thanks ___ Gnustep-dev mailing list Gnustep-dev@gnu.org http://lists.gnu.org/mailman/listinfo/gnustep-dev
Re: Private library symbols...
Richard Frith-Macdonald wrote: On 16 Oct 2006, at 04:13, Sheldon Gill wrote: Hi Richard, You've made some recent changes to base with the idea of making private functions in base more obviously private and less accessible. Yes ... as obviously private as possible. It seems to be that there is really only one goal with these changes: applications/tools shouldn't be using private functions in base Is there any other objective that I'm missing? Well, that's the main tactical objective ... the strategic objective is to improve maintainability ... so centralisation and clarification internally is almost as much of a goal as simply trying to ensure that external apps/tools don't use private stuff. Okay. If this is the case, I think the approach being taken here isn't the one which we should be pursuing. The original situation is we have functions like these: NSString *GSLastError(int); BOOL GSEnvironmentFlag( const char *, BOOL ); which make these functions seem like GNUstep API additions but really they are private. What has been done is create an artificial object @interface _GSPrivate : NSObject + (NSString*) error; @end @interface _GSPrivate (ProcessInfo) + (BOOL) environmentFlag: (const char *)name defaultValue: (BOOL)def; @end Yes, the idea is to collect everything together as much as possible, making it easier to find these things and making it clear that the various mechanisms are used internally. Now I say artificial because it doesn't conform to an object design. There never is an actual instantiation, for example, so you're always sending messages to the class. There are many other things which make this not really an object. This is a work in progress ... I'm not sure yet whether it would be good to have an instance and use instance methods rather than just a class and use class methods. The main reason for using a class is to use language features to support encapsulation and maintainability rather than depending solely on conventions. Well, you actually are relying on conventions anyway. You've called the class _GSPrivate using the underscore convention to indicate privacy. Also, these are private function calls within the library. Encapsulation doesn't really apply here. Doing this adds many more bytes to the library. It also makes these method lookups rather than function calls so they are slower. True, but these are very minor overheads and I think clarity and maintainability come first before looking at optimisation (obviously we can optimise by caching method IMPs or by using a struct as a dispatch table rather than using a class). I'm quite aware of how we can optimise method calls but this isn't really optimisation. I also find this inconsistent with your previous statements about avoiding 'bloat', as you put it. Surely more size and less speed for no functional changes is the very essence of 'bloat'? I don't agree that these changes make anything more maintainable or easier than simply decorating the function calls with an underscore in the conventional way. So we've added an artificial/strange object, increased the library size and slowed down those function calls all in an effort to prevent applications using our private functions. Is this right? As you can tell from my answers above, it's only partially right. Now its long been idomatic to use the underscore to mark private symbols. In fact, this is precisely what you've done with the class name. Yes, I've tried to use every signal I could think of ... the leading underscore, the word 'Private' the exclusion from any external headers and reduced linker symbols, and the inclusion of comments. Further, I think this makes navigating the source harder. Quick, tell me without searching where you're going to find the implementation for the above two functions? I'm very surprised at this comment ... since a big part of the intent is to make navigating the source *easier* and I believe this is achieved. I certainly think it's not obvious where the old functions were ... but the new methods are clear since the category names tell you where the individual method implementations in each group are, the declarations are all in a single place, and you can find all the private methods implementations easily using a search for @implementation _GSPrivate. Making sure all declarations are in GSPrivate.h is good but a matter of programmer discipline and has no bearing on the function call vs class method issue. That's a big improvement over the older code. Conventional layout has private functions near the top of the source file, just after header includes. They aren't that hard to find. Especially if you keep to convention with the underscores. Sure, the category names help you find where the particular function is located. I've an equivalent way which adds precisely 0 bytes to the libnrary and makes no impact on the runtime: //