From: John B. <joh...@ne...> - 2000-08-14 13:51:55
|
> > 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'. > > 2) In general, methods return true on success, undef or () on failure Yes, > > this means you can't tell the difference between 'no data' or 'error'. If > > the user doesn't care that's fine (since they may need to handle 'no data' > > as an application error anyway). Otherwise we could set $! (or $@?) and/or > > provide a 'did an error happen' function. > > I can see why some people may want this. But I am not sure I like it > too much. It should be OK for any app which wants to attempt to get data and can throw an error if it can't get it. If the app is implementing recovery then the user is 'sophisticated' and can use straight 'Net::LDAP'. > > 3) Object destructor does an unbind and closes the socket. (Not sure if > > Net::LDAP does this already...probably) > > No it does not. And I am not sure about the unbind, I have had bad experiences > with other modules doing quit on DESTROY. An perl will close the socket > anyway. Fair enough. > > 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. > > 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? 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. > 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 :-) > > 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 :-) > > - 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. > > - The 'cooked' entries support simple retrieval of scalars. If attr is > > multi-valued simply give back first. Provide ->get_all() get an array of > > all values back. > > I would prefer to just make get context sensetive. Ditto last comment. > > 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". This is why I was thinking inheritance might be bad, since it might appear to mix the two. > > 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 :-) > > 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. 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. regards, jb |