views:

83

answers:

3

I'm coding up a framework (in Java, but question is generic) in which I will provide a set of interfaces for clients to implement. The functions in the framework are going to rely on how the implementation classes will be constructued, that is, thay depend on those implementations to provide other instances of interfaces.

For example I might have:

Interface IContribution {
   public IMyStuff getMyStuff();
   public IHelper getHelper();
}

Interface IMyStuff {
     public void doSomeMethod(IHelper helper);
}

How can I make sure that those instances of IMyStuff and IHelper are available?

One method would be to create the 'getter' methods in the interface and in my framework painstakingly check for null objects returned.

Another option would be to create abstract classes that implement a factory that calls (using a strategy patterns) the interface methods to be implemented. But this defies the fact that I have the interface in the first place. Clients should then use the abstract class. But they could circumvent this by using the interface instead of the abstract class. Therefore I should not provide the interface but only the abstract class...

So, what are your ideas on this, what is a pragmatic approach to this?

+2  A: 

How can I make sure that those instances of IMyStuff and IHelper are available?

If the clients are responsible for implementing the interfaces and classes themselves, I would say it's their responsibility to make sure that those instances are available - I wouldn't concern myself with putting it in my own code.

matt b
Any framework should exist to provide tools for the programmer to use, however it is ultimately up to the programmer to use the tool and to implement the tool appropriately. Good documentation is really all you need.
AlbertoPL
Exactly. From your question it sounds like you're in some kind of battle with your users -- "if I do this, they can circumvent it and do that..." -- be sure that if a user decides to misuse your framework, they are going to succeed. But you're not writing a framework for the abusing user, you're writing it for a user who (hopefully) wants things to work. Just documenting the fact that the interface methods must return valid objects should suffice, and even that might be slightly redundant. You could check for nulls to be more accommodating of mistakes, but that's really all there is to it.
Avish
Ok, right, so there's no guarantee. Smart checks here and there should catch most serious errors, but the rest then boils down to having good documentation.
nojevive
+1  A: 

In order to build a good framework, you need to simultaneously be building an application around it. That way you will know and understand the pain your clients will endure BEFORE it is foisted upon them.

In other words, start with: How would my clients work with this application? How do they need to work with it?

You will immediately realize that the simplest way, from their perspective, is going to be best.

Chris Lively
Thanks, great 'best practice' advice.
nojevive
A: 

You can't ensure it with Interfaces alone, no behaviour there.

I agree with the philosphy of defensive programming in the Framework, help the developers avoid making mistakes.

You can supply a factory object:

public class MyPoliceman {
    public IContribution makeContributor( IMyStuff stuffer, IHelper helper)
                    throws BadAssociatesException {

     // check validity of stuffer and helper here, throw exceptions if null
    }
}

Then at least we can check for nulls etc.

With some thought it's usually possible to give the developers help. In some cases the best you can do is to trap errors and report them craefully. For example here, a perfectly fine IHelper could be passed to your factory, but later actions on the class could render it incapable. (eg. Image it was a File, and a side effect later closed the file.) Then all you can do is trap the resulting error condition, record an error somewhere and (likely) throw an exception. Then at least the developer has a clue about what to fix.

djna