6

Imagine I have an interface:

public interface MyInterface
{
    void CallMeFirst();
    void CallMeDuringApplicationLifecycle();
    void CallMeOnApplicationExit();
}

What is the best way of enforcing the order in which the methods on this interface are consumed by calling code?

It should be an exception if the methods are called in the wrong order.

It should also be an exception if any of the methods are not called at all.

4 Answers4

6

What is the best way of enforcing the order in which the methods on this interface are consumed by calling code?

You can't. Even if your implementations enforce exceptions, you can't guarantee others will.

Methods that care about their order have what is called temporal coupling, which adds a pile of fragility to the code. Where possible, you should redesign the code so that the methods can act independently.

That said, there are some things you can do in certain situations:

  1. Use an abstract base class. You can then enforce some behaviors while leaving others abstract for implementers to supply.

  2. Have multiple classes. When you call the first method, it returns a new object that lets you do the second step. The second method returns a new object that lets you take the third step, and so on.

None of those solve the "if no methods are called" scenario - you necessarily need something to check, but without more details I'm not sure how to approach that problem.

Telastyn
  • 110,259
6

A neat solution would be:

public interface First 
{
    Second doFirst();
}

public interface Second
{
    Third doSecond();
}

public interface Third 
{
    void doThird();
}

One might call:

FirstFactory.create()
    .doFirst()
    .doSecond()
    .doThird();

but cannot call:

FirstFactory.create()
    .doFirst()
    .doThird()
    .doSecond();

Another technical solution (but pretty bad from design perspective):

public interface MyInterface
{
    First CallMeFirst();
    Second CallMeDuringApplicationLifecycle(First first);
    void CallMeOnApplicationExit(Second second);
}

and make somehow First and Second inner classes of the implementing class of MyInterface. The call could be:

CallMeOnApplicationExit(CallMeDuringApplicationLifecycle(CallMeFirst()));
Random42
  • 10,520
  • 10
  • 52
  • 65
4

Maybe consider the Template Method design pattern. Your design introduces temporal coupling, which introduces risk and could be considered to be a design flaw.

4

m3th0dman showed the general principle, but his solution doesn't quite fit the problem as I understand it, since your method names make me think that CallMeDuringAPplicationLifecycle can be called multiple times.

In C#, a resource that needs cleanup (such as flushing buffers or closing connections) should use implement IDisposable.

interface IConnectionFactory
{
  IConnection connect(); // This is CallMeFirst
}

interface IConnection : IDisposable
{
  void send(); // This is CallMeDuringApplicationLifecycle
}
// And the Dispose() method of IDisposable is CallMeOnApplicationExit.

This way, you enforce that CallMeFirst is called first, because there's no other way to obtain an IConnection. And because C# programmers recognize IDisposable, they know that they have to call Dispose when they're done with the connection. You cannot actually enforce this in C#, so this is as close as you can get. (You can also write a finalizer that checks that Dispose was called, but you can't do anything but log the mistake there, and there's no guarantee that finalizers will be called.)