Thread: [pygccxml-development] single/multiple select interface
Brought to you by:
mbaas,
roman_yakovenko
From: Roman Y. <rom...@gm...> - 2006-03-12 09:07:12
|
Hi. I did not had much time this weekend to work( write ) some conclusions from our conversation :-). I reviewed documentation you wrote - perfect. I like the work you did. Thanks. Also, after my conversation with Matthias I think, that I fully understand the issue. The main question is: does class module_builder_t ( mb ) should have 2 different sets of select functions: the first one for selecting single instance of declaration the second one for selection multiple instances of declarations or should it have only second one ( multi-select )? Here is discussion that I hope will guide us to the right answer. First of all, I think that this is obvious, that an user can use only s= econd approach to select 1 instance of declaration and to work on it. The main Matthias point, please correct me if I wrong, is that the user does not have to know= on how many instances he works. Here is some possible implementation of Matthias API: [1] class module_builder_t: def member_function( self, ..., num_expected=3DNone ): mfs =3D some magic code that according to criteria will return list= of all member functions. if None is num_expected: return multi_decl_wrapper_t( mfs ) if num_expected !=3D len( mfs ): raise RuntimeError( "unexpected number of mem functions, that match criteria: ...." ) if num_expected =3D=3D 1: return mfs[0] #In this case we also can return multi_decl_wrapper_t( mfs ) #that will behave as an instance of the class #but this is also tricky and dirty to implement i= t. return multi_decl_wrapper_t( mfs ) Here is some possible implementation of s/m select interface: [2] class module_builder_t: def member_function( self, ... ): mf =3D some magic code that according to criteria will return single instance of matched member function or exception will be raised return mf def member_functions( self, ..., num_expected=3DNone ): mfs =3D some magic code that according to criteria will return list= of all member functions. if None is num_expected or num_expected =3D=3D len( mfs ): return multi_decl_wrapper_t( mfs ) else: raise RuntimeError("unexpected number of mem functions, that match criteria: ...." ) Now I am going to compare 2 approaches from an user point of view. 1) In [1] function name is member_function, while in [2] it is member_funct= ions. I think that "s" is essential. First time when an user starts to use this A= PI it could be confusing. I think he will expect one m.f. but will get some ot= her class instance. 2) Return type of functions depends on num_expected argument. This one could also confuse. 3) Lets see some ( =3D=3D my :-) ) patterns that an user has, while exporti= ng C++ library: 3.1 There are a lot of cases, where I need to work on whole library and= I don't care on how many instances I work. For example: exclude all functions that takes as second argument pointer to X. In this case I want to = use multi decl select mfs =3D module_builder.member_functions( .... ) mfs.exclude() 3.1 There are also a lot of special cases. May be in future we will hav= e less of them, but right now they do exists. So single select is ver= y useful here: mf =3D module_builder.member_function( .... ) mf.arguments[3].default_value=3D"std::string()" If I will use [1] approach, I always will be forced to add a "num_expected" argument. The main point in this example is that I do want to know the number of instances: 1 or many. I think that setting explicit number of expected instances is annoying. I am not against "num_expected" argument, I think that Matthias has some use case, where he needs this. ( By the way I'd like to see it :-) ). So we actually can add it. 4) Small plus that I see for [1] approach is number of API user should see/learn. But I don't think that this is makes big difference. 5) How can an user rename all overloaded functions? mfs =3D module_builder.member_functions( .... ) mfs.rename( "......" ) In both solutions it simple 6) An other problem that I see in [1] approach. We want multi_decl_wrapper_= t to behave, as it is an instance of some declaration decorator/wrapper. We c= an implement such behaviour only for "set" properties and functions that user does not care about their return values. "get" properties could not be implemented at all. So, as you can guess I am for different interfaces for single and multiple selects. Also, I understand, that I could be wrong and more over I do not get right an user desire/needs. I am asking you to try to understand my points. Also, it woul= d be nice to see where I am wrong. Thought, comments? Thanks -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Matthias B. <ba...@ir...> - 2006-03-13 10:45:50
|
Roman Yakovenko wrote: > 1) In [1] function name is member_function, while in [2] it is member_functions. > I think that "s" is essential. First time when an user starts to use this API > it could be confusing. I think he will expect one m.f. but will get some other > class instance. I agree that distinguishing between a "1-result" and a "n-result" query has its merits. It's a much shorter form of the assert_count argument which enables the query function to perform a check on the number of declarations found. > 2) Return type of functions depends on num_expected argument. This one > could also confuse. I think this is only a weak point. In my opinion, the exact type of the result is an implementation detail that should be of no interest to the user. The only important thing is what *interface* the resulting object(s) provide. And here, I'm in favor of keeping the interface identical (at least as far as decoration is concerned) no matter if the result references one single object or several objects. > 3) Lets see some ( == my :-) ) patterns that an user has, while exporting C++ > library: > [...] > If I will use [1] approach, I always will be forced to add a > "num_expected" argument. Why are you "forced" to do so? In my practical experience with my API this has not been the case and I was using the explicit assertion only in one single place. When you do queries for anything else than methods, then the cases where the user could be confused are rather rare. Suppose the user queries one particular class in some namespace: ns.Class("Foo") I believe your concerns so far have been that this might confuse a user when the result actually references more than one class. But when can that happen at all? C++ doesn't allow several classes with the same name in one namespace, so the undesired extra class must come from a namespace that lies within the ns namespace. In my case, I knew already in advance that all Maya classes are located in the standard namespace and there are no children namespaces that carry classes with the same name, so a line like the above could *never* reference more than 1 class and that's why I didn't need to add the assert_count argument to my queries. Don't get me wrong, I'm not arguing against the single/multiple interface. In fact, in a case like the above I agree that it is even superior because pyplusplus has more information about what the user actually intends (and it gets this information with very little effort from the user). I just wanted to point out that in most cases my version of the API is not as confusing as you make it sound sometimes. ;-) However, it does make a difference when selecting methods (more on that below). > 4) Small plus that I see for [1] approach is number of API user should > see/learn. > But I don't think that this is makes big difference. Agreed. This is only a minor (or even irrelevant) point. > 5) How can an user rename all overloaded functions? > mfs = module_builder.member_functions( .... ) > mfs.rename( "......" ) > In both solutions it simple Now that's the area where my concerns have actually been. In the above example the user *must* know in advance that he's dealing with a set of overloaded methods, and I think it could happen that he isn't really aware of the fact that a method has overloads. What if we treat a set of overloaded methods like one single method? I might argue that conceptually they already are one single method and it's only a syntax peculiarity of C++ that they have to be defined as separate methods (whereas on the Python side they will be combined to one single method again). > 6) An other problem that I see in [1] approach. We want multi_decl_wrapper_t > to behave, as it is an instance of some declaration decorator/wrapper. We can > implement such behaviour only for "set" properties and functions that user > does not care about their return values. "get" properties could not be > implemented at all. I was always using the result of a query for decorating the declarations, so there was no case where I had to read attributes. But this could still be handled as follows: If all declarations return the same value for a particular attribute then this value is returned, otherwise None is returned or an exception is thrown. Basically, I'm in favor of the single/multiple result distinction because it provides additional information to pyplusplus which can be used for checks. The only problematic case is the presence of overloaded methods. Maybe I like the above exception best (i.e. to treat them as one single declaration). - Matthias - |
From: Roman Y. <rom...@gm...> - 2006-03-13 13:40:29
|
On 3/13/06, Matthias Baas <ba...@ir...> wrote: > Roman Yakovenko wrote: > > 1) In [1] function name is member_function, while in [2] it is member_f= unctions. > > I think that "s" is essential. First time when an user starts to use th= is API > > it could be confusing. I think he will expect one m.f. but will get som= e other > > class instance. > > I agree that distinguishing between a "1-result" and a "n-result" query > has its merits. It's a much shorter form of the assert_count argument > which enables the query function to perform a check on the number of > declarations found. Good. > > 3) Lets see some ( =3D=3D my :-) ) patterns that an user has, while exp= orting C++ > > library: > > [...] > > If I will use [1] approach, I always will be forced to add a > > "num_expected" argument. > > Why are you "forced" to do so? In my practical experience with my API > this has not been the case and I was using the explicit assertion only > in one single place. May be because I want to track changes. Or may be, I want to be sure that this is special case and it was applied only on single declaration. > When you do queries for anything else than methods, then the cases where > the user could be confused are rather rare. Suppose the user queries one > particular class in some namespace: > > ns.Class("Foo") > > I believe your concerns so far have been that this might confuse a user > when the result actually references more than one class. But when can > that happen at all? C++ doesn't allow several classes with the same name > in one namespace, so the undesired extra class must come from a > namespace that lies within the ns namespace. > In my case, I knew already in advance that all Maya classes are located > in the standard namespace and there are no children namespaces that > carry classes with the same name, so a line like the above could *never* > reference more than 1 class and that's why I didn't need to add the > assert_count argument to my queries. So you do know the library you wrap :-). Also, while reading this code user should remember that "recursive" flag value. In single select he does not n= eed - module builder will do the job. > Don't get me wrong, I'm not arguing against the single/multiple > interface. In fact, in a case like the above I agree that it is even > superior because pyplusplus has more information about what the user > actually intends (and it gets this information with very little effort > from the user). :-) We are talking about high level API, so I do want to argue a little :-)= . Also it was my filling, that you do not want to provide single API, because you can achieve same effect using multi select version. > I just wanted to point out that in most cases my version of the API is > not as confusing as you make it sound sometimes. ;-) Sorry, I tried to build a disscussion based on facts only, but it is too difficult :-). > However, it does make a difference when selecting methods (more on that > below). > > 5) How can an user rename all overloaded functions? > > mfs =3D module_builder.member_functions( .... ) > > mfs.rename( "......" ) > > In both solutions it simple > > Now that's the area where my concerns have actually been. > In the above example the user *must* know in advance that he's dealing > with a set of overloaded methods, and I think it could happen that he > isn't really aware of the fact that a method has overloads. > > What if we treat a set of overloaded methods like one single method? I > might argue that conceptually they already are one single method and > it's only a syntax peculiarity of C++ that they have to be defined as > separate methods (whereas on the Python side they will be combined to > one single method again). There are few possible solutions to the problem, but I prefer to solve them next week, after we will have some high level api that actually work. > > 6) An other problem that I see in [1] approach. We want multi_decl_wrap= per_t > > to behave, as it is an instance of some declaration decorator/wrapper. = We can > > implement such behaviour only for "set" properties and functions that u= ser > > does not care about their return values. "get" properties could not be > > implemented at all. > > I was always using the result of a query for decorating the > declarations, so there was no case where I had to read attributes. > But this could still be handled as follows: If all declarations return > the same value for a particular attribute then this value is returned, > otherwise None is returned or an exception is thrown. Well, now we don't have to define the behaviour :-) > Basically, I'm in favor of the single/multiple result distinction > because it provides additional information to pyplusplus which can be > used for checks. Good. It was important to me to get your agreement. Now I also can work on high level API. Allen if you don't have some strong arguments against s/m select interfaces I am going to implement that interfaces. > The only problematic case is the presence of overloaded methods. Maybe I > like the above exception best (i.e. to treat them as one single > declaration). After we will have some initial version we can try to implement different solution. > - Matthias - > Thanks for comments. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Allen B. <al...@vr...> - 2006-03-13 23:20:33
|
>Good. It was important to me to get your agreement. Now I also can work >on high level API. > >Allen if you don't have some strong arguments against s/m select interfaces >I am going to implement that interfaces. > > I like the s/m select interfaces. -Allen > > >>The only problematic case is the presence of overloaded methods. Maybe I >>like the above exception best (i.e. to treat them as one single >>declaration). >> >> > >After we will have some initial version we can try to implement >different solution. > > > >>- Matthias - >> >> >> > >Thanks for comments. > >-- >Roman Yakovenko >C++ Python language binding >http://www.language-binding.net/ > > >------------------------------------------------------- >This SF.Net email is sponsored by xPML, a groundbreaking scripting language >that extends applications into web and mobile media. Attend the live webcast >and join the prime developer group breaking into this new coding territory! >http://sel.as-us.falkag.net/sel?cmd=k&kid0944&bid$1720&dat1642 >_______________________________________________ >pygccxml-development mailing list >pyg...@li... >https://lists.sourceforge.net/lists/listinfo/pygccxml-development > > > |
From: Roman Y. <rom...@gm...> - 2006-03-14 05:06:05
|
On 3/14/06, Allen Bierbaum <al...@vr...> wrote: > > >Good. It was important to me to get your agreement. Now I also can work > >on high level API. > > > >Allen if you don't have some strong arguments against s/m select interfa= ces > >I am going to implement that interfaces. > > > > > I like the s/m select interfaces. Good. One step to having better interface > -Allen -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |