views:

75

answers:

5

Hi,

Let's say we have an interface 'IA' for which we have an implementation 'A'. In our application domain, object 'A' never exists without a container object 'X'. So 'A' is never directly operated upon. 'A' aggregates in 'X'.

We don't want to expose 'A' to the outside world. For this we have taken the approach, not to have the public interface 'IA' and directly use implementation 'A' inside 'X'. Somehow I feel this is not the correct way. May be I am missing some fundamental OO concept.

Please opine.

PS: The reason for not providing 'IA' was given as: people might come up with their own random implementation for A and play with the system.


Ok. Let me put the actual problem here. I'm working on a web application. We have several layers - Dao, Doamin, Service, Web. Service layer provides various services on Domain objects through DAOs. We have domain objects - Wire and WireRequest. A WireRequest can have any number of Wires. Corresponding to these domain objects, we have two services - WireService and WireRequestService. WireService is injected in WireRequestService using spring.

When we expose our service.jar to clients they can potentially use the WireService independently and create Wire objects without WireRequest objects. We want to prevent that. Basically we want to control access to some services. (we could do this via authorization spring aspect, but wanted to use some OO way)

-Nayn

A: 

Why not make all methods and properties of A protected?

Kenaniah
+1  A: 

Do the simplest thing that could work.

Unless I'm missing something there's nothing inherently "non-OO" about hiding implementation details of aggregated objects or indeed any other attributes of your classes.

So as Kenaniah says, mark class A internal (or whatever the equivalent is in your language) and it won't be visible from the outside world. The collection property on your class can then be protected (or whatever) and it won't then be visible outside that class.

Some languages, e.g. .NET, also provide "inner classes":

public class X
{
    internal class A
    {
    }

    protected IEnumerable<A> ACollection { get; set; }
}

Here, A isn't visible outside of X at all.

Jeremy McGee
The basic concept of your advice is sound. Unfortunately your example only limits access to the collection, not the type, which makes it accessible via *new X.A();* That's counter to the OPs goals. He wants to prevent instantiation. If you declared A as *internal class A {...}* and the accessor as *internal* as well you'd have library level isolation of the classes which is what the OP wants.
Jason D
@JasonD - indeed. I've updated the response.
Jeremy McGee
@JeremyMcGee: I got the spring level idea from your answer.
Nayn
A: 

Let me see if I understand it right; rephrasing the problem, you have container X, which hold instances of A, which derive from IA - but so that X would only have instances of A, you restrict it to hold only types of A and not IA. Am I getting it right?

To me, this is actually fine. You are defining a constraint which can be reinforced during compile time. It is still valid to have the interface IA just for other purposes - you might need another list of objects which have the behaviour defined by IA; it is still useful to pass object references by interface IA for polymorphism and etc.

The only pitfall is that the system is closed - the list can only take type A. What if next time you need to hold both A and B in the same list, but then not C? (Assuming all derive from IA). It is much better to add in proper validation of data/states in such cases rather than restricting to one type.

Extrakun
A: 

Depending on the complexity of A, and the relative complexity (or simplicity) of X, it sounds like what you've described could be a Facade Pattern or a Wrapper/Adapter Pattern

Either is perfectly valid for a given set of scenarios and are often useful for keeping things clear across domain/sub-domain boundaries.

Edit: Given the OPs most recent addition...and it's sounding like "How do I control access to WireService and Wire when using spring and code injection..."

I'm unfamiliar with spring and how it injects things.
But if it obeys any sane rules for library creation it should only require those things you want consumers to have to be public... So you should be able to keep WireServiceRequester as the only public object. Give everything else a public interface that they implement, and remove the public from before any of the concrete implementation classes.

If spring isn't as sane as I'm assuming, then you're probably safest using the access control mechanisms built into spring...

Jason D
I updated the question. Please take a look if it makes sense.
Nayn
It's still not a question. It's clarifications on what your specific situation. Try to formulate a couple of questions to follow up the context. Such as:*Is what I'm doing appropriate? Are there design patterns that cover these scenarios? Is there another way to solve this problem?....etc.* We can infer what information may be most important to you, however, we're only guessing. Asking specific questions allows the community to more readily provide relevant and meaningful feedback. That ultimately helps you.
Jason D
Hmm. I appreciate that a lot. I think you understood my question correctly.I got one very simple solution to this problem.Spring takes care of dependency injection by actual object creation.I can define the 'wireService' bean as an inner bean to 'wireRequestService' bean. Since inner bean can not be used outside the container bean, it can not be created independently.It is the same concept as that of inner classes. I guess this serves my purpose. Thanks a lot guys.
Nayn
A: 

the public service.jar should only contain interfaces classes and the implementation should be obtained via some sort of IoC

in this case, using spring to bind the implementation dynamically

therefore the service.jar should contain

WireRequestServiceInterface only

Dapeng