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.

  • Do you have working code? If so, post your question on http://codereview.stackexchange.com/ – rory.ap Mar 09 '16 at 15:00
  • Thanks for the link @roryap. I wasn't aware of the code review site - looks useful. However, this question is more of a generic issue that I come across quite freqently; is there a pattern that I could use to enforce how an interface is consumed. – James Bateson Mar 09 '16 at 15:09
  • 2
    This looks like an interesting question I'd ask on [programmers.se]. The issue is that you have *temporal coupling*, and the purpose of an interface isn't to enforce anything other than the *presence* of a given set of members. There is no way an interface can enforce anything like you're asking, let alone throw exceptions. – Mathieu Guindon Mar 09 '16 at 15:13
  • 1
    Interfaces expose an ... interface. Not a process. You are talking about *process* management. This can be handled by a workflow, a state machine, or many other mechanisms – Panagiotis Kanavos Mar 09 '16 at 15:14
  • Thanks @Mat'sMug. You are right, there is clearly temporal coupling here. I can see how an approach like [this](http://blog.ploeh.dk/2011/05/24/DesignSmellTemporalCoupling/) can be used to remove temporal coupling for simple initialization. However, I can't see how it would help if you needed to call a method _after_ this initialization. My current problem involves me having to flush a buffer to a server and I want to do this only once on application exit. – James Bateson Mar 09 '16 at 15:40
  • 1
    Does this answer your question? [How to make sure people call methods in the right order?](https://softwareengineering.stackexchange.com/questions/294455/how-to-make-sure-people-call-methods-in-the-right-order) – gnat Dec 16 '22 at 22:21

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
  • 108,850
  • 29
  • 239
  • 365
  • 1
    The multiple classes / multiple interfaces scheme seems like the most watertight. – Mike Mar 11 '16 at 03:15
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,370
  • 10
  • 48
  • 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.

David Osborne
  • 405
  • 4
  • 8
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.)

Sebastian Redl
  • 14,950
  • 7
  • 54
  • 51