views:

326

answers:

5

I'm trying to convince a colleague that a function should take an interface as a parameter, and not the object itself. I think small objects can be fine to pass across, but for large ones I would give them an interface and just pass the i/f over, not the whole thing.

Note that there will only ever be one of these large classes - the i/f will never be used for a different object. This is merely for hiding the implementation of an object.

Would you agree that separating a large class into an interface(s) is good practice?
Are there any disadvantages to doing this?

Example:

public interface class IVeryLargeClass
{
    void DoSomething();
    ...
};

public ref class VeryLargeClass : public IVeryLargeClass
{
public:
    virtual void DoSomething() { ... }
    ...
};

public ref class AnotherClass
{
public:
    AnotherClass(VeryLargeClass^ vlc)  { vlc->DoSomething(); }
 // OR
    AnotherClass(IVeryLargeClass^ vlc) { vlc->DoSomething(); }
};
+6  A: 

The Dependency Inversion Principle can be summed up as: It is better to depend on abstractions than concretions.

It's almost always better to pass an interface than it is to pass a concrete class.

That said, high cohesiveness against internal types is ok within a particular module, but that's very subjective as to when and how you should pass concrete objects.

Randolpho
+11  A: 

One of the first principles you learn in OO development:

Program to an interface, not an implementation.

You indicate that "there will only ever be one of these large classes - the i/f will never be used for a different object". This might be true in your case, but I wish I had a nickel for every time such a statement turned out to be wrong.

In addition to considering whether there might be multiple implementations of your interface, you should also consider whether your concrete object exports (or might export) additional methods that do not share a logical affinity with the operations declared in the interface. In such a case, you could simply declare the additional operations in one or more additional interfaces. A client, then, need only couple with the interface that exports the operations in which it is interested.

Put simply, interfaces provide a means of managing the coupling between clients and providers.

Brandon E Taylor
+3  A: 

If you pass an implementation, you kind of loose one of the advantages of using interfaces, meaning separating the logic from the actual implementation.

The interface of a software module A is deliberately kept separate from the implementation of that module. The latter contains the actual code of the procedures and methods described in the interface, as well as other "private" variables, procedures, etc.. Any other software module B (which can be referred to as a client to A) that interacts with A is forced to do so only through the interface. One practical advantage of this arrangement is that replacing the implementation of A by another one that meets the same specifications of the interface should not cause B to fail—as long as its use of A complies with the specifications of the interface (see also Liskov substitution principle).

http://en.wikipedia.org/wiki/Interface_(computer_science)

marcgg
+3  A: 

I'd prefer to avoid creating and interface for the sake of creating an interface. If you can use that interface in more than one place, then you have a winner - or if this is a public function and class and you specifically want to simplify.

Jon B
But with an interface, you can test your code by mocking the interface. In many languages (especially C#) you cannot effectively mock a concrete class.
Randolpho
@Randolpho - that's a good point. I'd just watch out that interfaces aren't taken to an absurd level or created in an ad-hoc fashion. They need to make sense as part of the design.
Jon B
That's a good point as well. Ultimately, the rule of thumb that I have is that if a class is to be used by something outside its module, it gets an interface. If it's used internally only (i.e. it's a helper class or something similar) it doesn't need an interface, but can usually benefit from having all methods being virtual (for easy mocking). In general, I take design-by-contract seriously.
Randolpho
+1  A: 

The other issue is your very large class itself. This may not be within the scope of what you're doing, but a very large class implies that it might be doing too much in the first place. Can you refactor it into smaller classess, where the information required within the function you're calling is encapsulated in its own smaller class? If you create an interface against that class you may find it that much more re-usable than against the very large class you currently have.

Gerry