From: David B. <d.b...@ma...> - 2000-08-15 03:46:17
|
Hi again, Why not handle the 'expected'? When using this hypothetical "on_error", if the operation has an obvious "operation failed" return, then die/croak/\&callback/whatever and If the operation has return codes that don't meet that criteria, then don't. Eg, 'compare', should really consider both a true and a false return value as being valid "operation successful"... since to get either of those values then compare had to succeed in the compare. What happens when compare has (for example) an internal error and/or the data was uncomparable for unknown reason? Is this handled at the moment? It should in my opinion be this is what could/should cause an on_error event in compare's case. And for that matter, by allowing a user-defined subroutine as an on_error, you could allow the user(programmer) to define a callback for 'compare' that dies/croaks/whatever whenever the user(programmer) desires (including error code 5 or 6). By doing this the API is simpler, the bloat is negligable, the users are happier, the resultant code is easier to read... what more could you want? I mean, the "|| die.." code will be written anyway so in the module is a better place for it, so it doesn't have to be written over and over again! As I understand it, this would also clear-up the problem the API currently has with it's inability to determine if a search returned no results because there was nothing to return or because of an error performing the search. My 2c. What do others think? David. At 07:46 PM 8/14/00 -0500, you wrote: >Problem with defining a default on_error is that some errors are expected. For example in >compare, the results will either be 5 for false or 6 for true (or is it vice/versa ?) > >mark > >David Bussenschutt wrote: > >> Bravo everyone, >> >> I can't add much more to the debate except to say I'm on the side of >> everyone that wants to make the Net::LDAP API simpler by default, but more >> powerful if desired. >> >> It seems to me that there are a lot of people out there doing : >> Net::LDAP->some_op( blah blah ) || die ("some op failed $!"); >> >> How's this for another optional feature... >> >> my $a = Net::LDAP->new("ldap.server.org",on_error=>die); >> my $a = Net::LDAP->new("ldap.server.org",on_error=>croak); >> my $a = Net::LDAP->new("ldap.server.org",on_error=>carp); >> my $a = Net::LDAP->new("ldap.server.org",on_error=>\&myfunction()); >> >> Obviously, the on_error value would apply to all >> binds/queries/searches/lists/reads performed >> using that connection handle. >> >> David. >> >> At 03:30 PM 8/14/00 +0100, Graham Barr wrote: >> >On Mon, Aug 14, 2000 at 02:45:44PM +0100, John Berthels wrote: >> >> >> >> > > This leads me to think that a high level interface might be useful. >> Here >> >> > > are a couple of suggestions on how this might differ from Net::LDAP. >> >> > > >> >> > > 1) The ->new method takes an optional username/password and does a >> >> > > Net::LDAP->new and a ->bind. Returns object or under if anything fails. >> >> > >> >> > IMO, this is bad. I even want to move the connect out of new and into a >> >> > separate method so that errors can be returned with more ease. >> >> >> >> I agree that it would be bad for the Net::LDAP API. >> >> >> >> However, for an 'easy to use' interface (Net::LDAP::For::Dummies) I just >> >> want a handle for a connection I can do things with. If the API fails to >> >> create it (for any reason) then fine, return undef and put some >> >> descriptive text in $! but don't make me do 2 or 3 calls to get the >> >> handle. In the common case it will 'just work'. >> > >> >I am all for having some way for Net::LDAP to have "common use" functions. >> But >> >having a separate API "for dummies" no. >> > >> >> > > i.e. you could write: >> >> > > >> >> > > #!/usr/bin/perl -w >> >> > > use Net::LDAP::Cooked; # or whatever >> >> > > >> >> > > my $l = Net::LDAP::Cooked->new( "local.ldap.server" ) >> >> > > or die( "Can't connect : $!" ); >> >> > > my @staff = $l->list( "ou=staff, o=myorg" ) >> >> > > or die( "Can't list staff : $!" ); >> >> > >> >> > I think this is coming back to having someway, other than inheritance >> (maybe) >> >> > to extend Net::LDAP. >> >> >> >> Yes. Exactly. I suspect that lots of people writing apps using Net::LDAP >> >> have similar code in their apps. I want to pull that similar code into a >> >> companion module for Net::LDAP for standard code reuse reasons. >> > >> >Right, then lets define a way to do that. >> > >> >> > > foreach my $person( @staff ) { >> >> > > my $name = $person->get( "cn" ); >> >> > > my $phone = $person->get( "telephoneNumber" ); >> >> > >> >> > For the ::Entry I would prefer to keep one module and have it work as >> >> > expected. >> >> >> >> Again - expected by who? >> > >> >A perl programmer. >> > >> >> It may be possible to define an ::Entry API which >> >> satisfies both camps, but if not then why not have two? The 'hard core' >> >> users don't have the impact of the additional fluff and the 'just want it >> >> to work' users don't have to go through additional levels of indirection >> >> to get to their data. >> > >> >I don't think the two camps are that different in terms of >> 'understandability' >> >just in what level they want access to. >> > >> >> > And I think the above it the "expected" behaviour. Which would mean >> >> > that get returns a list and we add exists. Then we split out the >> >> > extra option code I added into another method, say get_nooptions >> >> > which always returns a hashref >> >> >> >> Something like this would be fine. The only negatives for this would be >> >> bloating the module and which camp was annoyed by having to use the longer >> >> name :-) >> > >> >It would not be bloat as all of it is there now. It just seems the API >> >is hard for some to understand. I belive we should be able to get a >> >single API ot ::Entry that is both powerful enough for the hard core >> >user and simple enough for the beginner. >> > >> >> > > The kinds of things going on here would be: >> >> > > >> >> > > - additional methods which reduce the need to construct arguments to >> >> > > ->search. e.g. ->list, ->read, ->exists >> >> > >> >> > What are ->read and ->exist and called on what object ? >> >> >> >> my $entry = $ldap->read( $dn ); # Call search with scope 0 and filter >> >> >> >> ->exists( $dn ) is true if the entry is in the Directory. At first sight >> >> seems the same as ->read( $dn ) but could be more efficient since it need >> >> not pull back all attributes. Both are syntactic sugar around ->search(). >> >> >> >> The previous discussions around $ldap->alive() (or $ldap->ping()) fit >> >> right in here too. Syntactic sugar. This is perl after all :-) >> > >> >Right. We need a way to add extensions. This can be done in many ways. >> > >> >1) Inheritance >> >2) MI >> >3) allowing others to import into Net::LDAP with a register module. >> > >> >> > > - avoid Net::LDAP::Message returns, give back arrays of >> >> > > Net::LDAP::Cooked::Entry >> >> > >> >> > I would rather just keep one Entry object. >> >> >> >> Fair enough, but see above regarding two audiences. >> > >> >I think we can keep both happy. >> > >> >> > > So, is this something which would be useful to people (or would have >> been >> >> > > useful to them when starting with Net::LDAP) or does it just hide >> too much >> >> > > from the user and is likely to confuse them? >> >> > >> >> > Confusion is one thing that concerns me. Because you teach them one >> >> > theng then they have to learn something else if they want to go >> >> > beyond its boundaries. I would prefer to make the API as natural/easy >> >> > as possible. >> >> >> >> This is a very good point. The documentation of all this would have to be >> >> done very carefully. To some extent I think that this might be alleviated >> >> by having the two APIs appear less related. "Oh...you're using >> >> Net::LDAP::Simple. Thats OK, but to do *that* you need to read up on >> >> Net::LDAP". >> > >> >Two documents, yes. Two APIs, I would rather not. >> > >> >We could just make these methods avaliable via the AUTOLOADer or have the >> >user type >> > >> > use Net::LDAP::Extn qw(:simple); >> > >> >to get Net::LDAP::Extn to import some subs into Net::LDAP or just have >> >Net::LDAP::Simple inherit from Net::LDAP and provide these subs. >> > >> >But some of these may be of use to 'hard core' users too, which is why >> >I don't really like the ::Simple appraoch as we will see more and more >> >::Simple being the main API. >> > >> >> This is why I was thinking inheritance might be bad, since it might appear >> >> to mix the two. >> > >> >Yes. >> > >> >> > > If this is something worth doing, should we add bloat to Net::LDAP to >> >> > > support things like this or should we create a wrapper module. >> >> > >> >> > bloat is something I want to avoid if possible. >> >> >> >> This is the main reason I was thinking about a second API, rather than >> >> trying to make one API all things to all people. >> >> >> >> > > If we create a wrapper module should it live within the Net::LDAP >> >> > > namespace or somewhere else? >> >> > >> >> > probably within. >> >> >> >> Agreed. (But its your namespace :-) >> > >> >But my preference is a way to provide extensions to Net::LDAP, but still >> >(maybe) via a Net::LDAP method. The other option is to provide subs >> >in Net::LDAP::Util >> > >> >> > > Should it inherit from Net::LDAP and add/override methods or should >> it be >> >> > > a seperate object? >> >> > >> >> > What would it gain from being a separate module ? I would say it >> >> > should inherit, if we have it at all. I would prefer to get the current >> >> > module "fixed" rather than create another module just to provide a >> different >> >> > API. >> >> >> >> My real question is whether it is better to extend Net::LDAP to make it >> >> easier for novice users (or those who like convenience) or instead to >> >> recognise that there are different types of users and so implement a new >> >> API to meet a different need. I think Net::LDAP is nice, clean and >> >> precise. I like that. I also find myself replicating wrapper functions >> >> from app to app and wishing that they lived in the distribution. >> > >> >What kind of wrapper functions ? give some examples >> > >> >Well we need to define a way for people to make these things easy. >> > >> >> As I see it, the downsides of extending Net::LDAP are bloat and >> >> conflicting design goals. The downsides of a new API are that it is a >> >> little more work. >> > >> >And the fact you end up with two APIs and people asking questions which to >> >use etc... >> > >> >I am sure it is possible to meet the demands of both camps without creating >> >a completely new API. >> > >> >This email is highlighting more than one issue. Lets break it into parts and >> >see what we can develop >> > >> > 1) Net::LDAP::Entry >> > 2) Extending Net::LDAP with common methods >> > >> >In the case of 1) lets list what we should be able to do with an Entry and >> >what a newbie would probably expect. Then compare that with what an expert >> >would expect/need. It may not be that different. >> > >> >Graham. >> > >> > >> > >> >> -------------------------------------------------------------------- >> David Bussenschutt Email: D.B...@ma... >> Senior Computing Support Officer & Systems Administrator/Programmer >> Location: Griffith University. Information Technology Services >> Brisbane Qld. Aust. (TEN bldg. rm 1.33) Ph: (07)38757079 >> -------------------------------------------------------------------- > > > > -------------------------------------------------------------------- David Bussenschutt Email: D.B...@ma... Senior Computing Support Officer & Systems Administrator/Programmer Location: Griffith University. Information Technology Services Brisbane Qld. Aust. (TEN bldg. rm 1.33) Ph: (07)38757079 -------------------------------------------------------------------- |