• Post Reply Bookmark Topic Watch Topic
  • New Topic

safe to assume package scope methods are only called by other package scope?  RSS feed

 
drew sollenberger
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a model with many objects that are interconnected. A user can create an object without 'putting it in memory', ie doesn't represent a perminate state. Once the user calls addToModel the model should update it' state, including updating any objects associated with it (for instance, if a path is added then the edges that make up that path need to be informed, as they keep a list of allk path's dependent on them). The problem is that I want all of these objects to appear as immutable to the controller and others using my model. I had considered putting everything in the same package so that the model objects can update each other to maintain their interconnected state; but no one outside of the Model package can mess with these objects. Public methods would allow fetching of state from these objects, but can't change/update any state without an explicit call to the Model. The Model would allow an add path or addEdge method, calling the apporpiate methods of the Path and Edge objects, and the objects would all sort out their own state from there.

Of coruse this only works if I'm certain that no public method (other then the Model's addPath and addEdge ones) ever make a call to the package scope methods. This makes me worried that it's not well encapsulated; I'm depending on those working on the Model objects to know not to call anything package scope from a public method. I would note such of course, but is that enough protection? Is this considered as unsafe as it seems? Is there any way to enfource the sort of contract I mentioned?
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

By package scope I presume you mean default access, which a lot of people call package‑private access.
You are correct that default access members are only visible inside their own package, but that does not guarantee encapsulation.
If you don’t lock the package somehow (e.g. by putting it into a “sealed” jar), somebody might add classes to yoru package which call those methods in a way you didn’t anticipate. Or even extend your classes by public classes and override those methods by public methods.

Anybody else got any suggestions, please?
 
drew sollenberger
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes your correct, when I say package scope I mean the default scope. Is there a reason you distinguish that as package-private rather then just staying package scope? Is there another scope that is better described as package?

I'm mostly okay with someone adding other elements to the package. We won't export this source code, so the only people messing with it are my own developers. I don't mind if new classes are added, *if* they abide by the contract of only caling package scope methods from other package scope (be they the same object, or another object in the package). I want the only class that can call a package scope method to be the Model class; or alternatively I may just have the edge provide a non-package scope method which takes care of adding into the state (*almost* everything can be added just by adding edges and paths (paths themselves only affecting the model via the possibility of adding an edge to complete the path). I would need a way to add nodes in some rare cases; but the only method that needs to be transparently callable to the user is addEdge, with maybe some helper methods for adding paths that are bassed off of the addEdge method).

I know that the java security module allows one to change ability to access methods. It may be possible to use the AccessController to enforce the requirement that calls to package scope methods of any of my Objects (which will all extend a default myObject class, making this easier) only come from package scope methods of classes in the same package. I don't know for certain rather AccessController even allows that level of refinment to begin with. Even if it does it would be a runtime exception instead of compile time; but a runtime exception that would presumably shwo up with even basic testing. Of course doing this in a way that someone who gets a access exception understands *why* he was forbidden from calling the package scope methods would be difficult. Plus, this still asumes an (admittedly less restrictive/more obvious) assumption that no object will change an objects internal state *except* via their package scope methods (unless I can use the accessController to restrict a class from changing it's own internal fields except in package scope methods; but I really doubt I have that kind of power). All things considered I don't know if using the AccessController makes things much better then doing nothing.

Is there a paradim I could use to allow the model to change state of it's objects while still preventing the external user from doing it and better encapsulating everything? I have heard a suggestion of using interfaces to provide 'immutability', by returning to my controller an interface of a class that only provides the getter methods and not the setters. However, I'm afraid that creating half a dozen new interfaces (one for each existing object) would clutter code and possibly confuse some other developers (less of a Software Engineering background, don't 'get' interfaces as well); and ultimately I don't think the interfaces protect from the *real* issue of keeping someone from trying to change model state from one of the public (or in this example, available in the interface) methods.
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I meant a lot of people apply the name package‑private to default access.
If you are sure nobody else will add code to breach your rules, then default access members are only accessible inside the package. Of course you can use reflection to change that, so you might need to enforce a security manager.

Anybody else got any suggestions please?
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!