Rules for Reflection Invocation

Posted by Laura Stern on 28-May-2015 14:13

In the Reflection specification that was posted for the 11.6 ESAP, it states that once you get an instance of one of the reflection objects, such as Progress.Reflect.Method, or Progress.Reflect.Property, you can invoke that method, or get/set the property value from any piece of code. 

This is different from the methods on Progress.Lang.Class (P.L.C), such as Invoke or  SetPropertyValue.  For those methods, normal OO rules apply.  Only Public class members can be invoked/set/etc from anywhere.  You can use these methods on Private class members only from within the class that owns the element and similarly protected class members can only be invoked/set/etc from a class within the hierarchy.

The rationale for allowing the functionality from anywhere is to allow tooling to work or to do things like writing your own serialization facility from outside the class that is being serialized.

However, we are considering changing the rules for the new Progress.Reflect objects for 11.6.   The default would be that you can only do Invoke/New/Get/Set/Subscribe operations on Public data members, period.  So this would actually be a little more restrictive than the current rules.  In a later release we can add a way to mark elements (details specifically left out) so that Invoke/New/Get/Set/Subscribe will work on them from anywhere.

Alternatively, we can keep the rules the way they are spec'd, i.e., everything is allowed from anywhere, and later add a way to restrict access for particular elements.

The option to follow the same rules as the current P.L.C methods is not under consideration.

Note that .NET takes the latter approach (accessible, unless work is done to make an element secure).  Whereas Java follows the approach of being more restrictive by default.

We'd appreciate any feedback on this, specifically use-cases that would call for following one approach vs the other.

All Replies

Posted by Mike Fechner on 28-May-2015 14:38

Hi Laura,
 
I hate to say, but in this case I am more on the Java side than on the .NET side…
 
As a framework vendor, I want to know, that what is defined PRIVATE or PROTECTED cannot be made de facto PUBLIC by using reflection. I do not make code PRIVATE or PROTECTED because I want to hide the functionality from our customers (they get full source code anyway). But especially PRIVATE methods are implementation details that I want to be able to change at a later stage without being worried that my customers get p…. o.. about this. And the experience I have made, that if customers can call something in any way (using reflection) they will use it. Potentially making my life harder when they complain about me changing or removing the method later.
 
For the same reason I need a package level protection option! You can add thousands of comments to a PUBLIC method like: /* This method is public, because another class in the same package needs to call into it for internal reasons that may change at any time without warning, so please don’t use it yourself. */
 
Regards,
Mike
Von: Laura Stern [mailto:bounce-stern@community.progress.com]
Gesendet: Donnerstag, 28. Mai 2015 21:14
An: TU.OE.Development@community.progress.com
Betreff: [Technical Users - OE Development] Rules for Reflection Invocation
 
Thread created by Laura Stern

In the Reflection specification that was posted for the 11.6 ESAP, it states that once you get an instance of one of the reflection objects, such as Progress.Reflect.Method, or Progress.Reflect.Property, you can invoke that method, or get/set the property value from any piece of code. 

This is different from the methods on Progress.Lang.Class (P.L.C), such as Invoke or  SetPropertyValue.  For those methods, normal OO rules apply.  Only Public class members can be invoked/set/etc from anywhere.  You can use these methods on Private class members only from within the class that owns the element and similarly protected class members can only be invoked/set/etc from a class within the hierarchy.

The rationale for allowing the functionality from anywhere is to allow tooling to work or to do things like writing your own serialization facility from outside the class that is being serialized.

However, we are considering changing the rules for the new Progress.Reflect objects for 11.6.   The default would be that you can only do Invoke/New/Get/Set/Subscribe operations on Public data members, period.  So this would actually be a little more restrictive than the current rules.  In a later release we can add a way to mark elements (details specifically left out) so that Invoke/New/Get/Set/Subscribe will work on them from anywhere.

Alternatively, we can keep the rules the way they are spec'd, i.e., everything is allowed from anywhere, and later add a way to restrict access for particular elements.

The option to follow the same rules as the current P.L.C methods is not under consideration.

Note that .NET takes the latter approach (accessible, unless work is done to make an element secure).  Whereas Java follows the approach of being more restrictive by default.

We'd appreciate any feedback on this, specifically use-cases that would call for following one approach vs the other.

Stop receiving emails on this subject.

Flag this post as spam/abuse.

Posted by Tim Kuehn on 28-May-2015 15:27

I'm with Mike on this.... if you let people play with the innards, they will, and then it'll be "your fault" when you change things and their code doesn't work any more... 

+1 on "package" access too. 

[collapse]
On Thu, May 28, 2015 at 3:39 PM, Mike Fechner <bounce-mikefechner@community.progress.com> wrote:
Reply by Mike Fechner
Hi Laura,
 
I hate to say, but in this case I am more on the Java side than on the .NET side…
 
As a framework vendor, I want to know, that what is defined PRIVATE or PROTECTED cannot be made de facto PUBLIC by using reflection. I do not make code PRIVATE or PROTECTED because I want to hide the functionality from our customers (they get full source code anyway). But especially PRIVATE methods are implementation details that I want to be able to change at a later stage without being worried that my customers get p…. o.. about this. And the experience I have made, that if customers can call something in any way (using reflection) they will use it. Potentially making my life harder when they complain about me changing or removing the method later.
 
For the same reason I need a package level protection option! You can add thousands of comments to a PUBLIC method like: /* This method is public, because another class in the same package needs to call into it for internal reasons that may change at any time without warning, so please don’t use it yourself. */
 
Regards,
Mike
Von: Laura Stern [mailto:bounce-stern@community.progress.com]
Gesendet: Donnerstag, 28. Mai 2015 21:14
An: TU.OE.Development@community.progress.com
Betreff: [Technical Users - OE Development] Rules for Reflection Invocation
 
Thread created by Laura Stern

In the Reflection specification that was posted for the 11.6 ESAP, it states that once you get an instance of one of the reflection objects, such as Progress.Reflect.Method, or Progress.Reflect.Property, you can invoke that method, or get/set the property value from any piece of code. 

This is different from the methods on Progress.Lang.Class (P.L.C), such as Invoke or  SetPropertyValue.  For those methods, normal OO rules apply.  Only Public class members can be invoked/set/etc from anywhere.  You can use these methods on Private class members only from within the class that owns the element and similarly protected class members can only be invoked/set/etc from a class within the hierarchy.

The rationale for allowing the functionality from anywhere is to allow tooling to work or to do things like writing your own serialization facility from outside the class that is being serialized.

However, we are considering changing the rules for the new Progress.Reflect objects for 11.6.   The default would be that you can only do Invoke/New/Get/Set/Subscribe operations on Public data members, period.  So this would actually be a little more restrictive than the current rules.  In a later release we can add a way to mark elements (details specifically left out) so that Invoke/New/Get/Set/Subscribe will work on them from anywhere.

Alternatively, we can keep the rules the way they are spec'd, i.e., everything is allowed from anywhere, and later add a way to restrict access for particular elements.

The option to follow the same rules as the current P.L.C methods is not under consideration.

Note that .NET takes the latter approach (accessible, unless work is done to make an element secure).  Whereas Java follows the approach of being more restrictive by default.

We'd appreciate any feedback on this, specifically use-cases that would call for following one approach vs the other.

Stop receiving emails on this subject.

Flag this post as spam/abuse.

Stop receiving emails on this subject.

Flag this post as spam/abuse.




--
Tim Kuehn:  Senior Consultant  - TDK Consulting Services
President - Ontario PUG 
Program Committee Chair - PUG Challenge Americas, 
Course Instructor: Intro to OO Concepts for Procedural Programmers

Skype: timothy.kuehn
Ph: 519-576-8100
Cell: 519-781-0081
[/collapse]

Posted by Paul Mowat on 29-May-2015 02:35

I also agree with Mike and Tim

Posted by Simon L. Prinsloo on 29-May-2015 02:42

I agree with Mike and Tim as well.

If I decided it is internal / private, it means the not even me may access it elsewhere and I need to be able to rely on that decision.

Posted by bronco on 29-May-2015 03:24

In Java the private members can be accessed as well, see: http://tutorials.jenkov.com/java-reflection/private-fields-and-methods.html

The article gives a use case as well (unit testing). Although I see the point made by the other gentlemen in this discussion, I would rule out the possibility to access the "privates" (sorry, couldn't resist). 

Edit: made the URL a true link

Posted by Mike Fechner on 29-May-2015 03:38

“I agree with Mike and Tim as well.”

And as one of our customers he’s one of those I want to hide stuff from  :-)

Posted by Paul Mowat on 29-May-2015 04:23

You know me to well :)

Posted by Marian Edu on 29-May-2015 14:34

I'm on the Java side (no surprise I guess), do like the setAccessible option to turn off access check... guess we can take the risk of a brute force attack from the crowd that tries to find private properties/methods :)

Unit testing private methods is hard anyway, most of the time I tend to go with protected/final just to get along this. Package level protection can easily be avoided with 'parallel' packages especially the way we use propath so that won't make me feel any more safe, inventive users will always find ways to lift that protection... the only joy I find is to see them suffer latter one because of that ;)

Posted by Mike Fechner on 29-May-2015 14:38

“Package level protection can easily be avoided with 'parallel' packages especially the way we use propath so that won't make me feel any more safe, inventive users will always find ways to lift that protection... the only joy I find is to see them suffer latter one because of that ;)”

Whenever I discussed the requirement for “package level protection” I discussed it along with “sealed” or “signed” PL files. Package level protection would be retricted to members of the sealed PL. Similar to assemblies in .NET.

Posted by Thomas Mercer-Hursh on 29-May-2015 14:49

I think Marian's idea is that you should just periodically make changes that may be arbitrary, but which will screw up anyone who tries to use what they shouldn't.  Maybe, after a while, they will learn not to do that. :)

Posted by Mike Fechner on 29-May-2015 14:52

Do THAT with your ABL2UML when you want to stop others from using it at all ;-)

Posted by Simon L. Prinsloo on 30-May-2015 05:22

We are all grown up and responsible for what we do. Each person in society has the responsibility to know the rules and abide, or carry the consequences. We know we must not speed on the high ways. Most of the time you would most likely get away with it. But when you are caught, you have to take the rap.

Protection, including package level protection, is not a policeman, but a road sign imposing (or lifting) some limit. It is a tool  assisting you to know the local rules. If your mind wander off and you start speeding, the GPS will see that and inform you that you are transgressing. You can adjust or you can simply switch it off. What you can't do, once you switched it off, is to claim that you did not know. The same goes for the compiler. It will protect me if I attempt to transgress, but if I intentionally take action to evade it, I can't blame anybody else when it comes back to haunt me.

When a programmer bestow a certain protection on something, the programmer signal a certain intent. This means that the rest of us have been informed and if someone do not head the warning, that person have to bear the consequences.

Another helpful benefit of protection comes in tooling, where you only see what is relevant. When I consume a class from a different package, it would be quite helpful and time saving if I only saw what is relevant, rather than to wonder if the developer intended that I use either CreateEntry() or NewEntry(), not knowing that one is part of the package's interface and  the other is actually for internal use. It gets worse if CreateEntry() is the package method, because once I find it, I will most likely stop reading and run into all sorts of trouble, not even realising that there is a better alternative. If it was clearly marked as package level, most of us will read on.

When we get to reflection, we are in essence bypassing the normal rules in order to achieve some non-functional goal, e.g. generating code or doing a unit test, rather than creating a financial transaction or issuing some certificate. In my mind it is advanced territory where most people do not need to go. But having rules in that domain to guide you when you enter it (e.g. using an option to intentionally make the private accessible) makes life much simpler for everybody than having cart blanch until you are stopped.

This thread is closed