4

I am currently implementing a class for a network protocol. The protocol uses a quite complex and extensive finite state machine. A pair of an event plus a state is mapped to a function, which does some work and sets the new state.

As there are about 150 valid state/event combinations and 28 distinct functions to be called, I refactored the whole state machine logic away from the associating/sending/receiving/... (let's call it service class) into a separate statemachine class. The problem is, that some of these 28 functions need access to the service class, for example to reset a deadline timer.

What I could do is befriend the statemachine class and the service class, so they can access each other's internals. This would introduce a very tight coupling (albeit natural, as they belong together). I could also just leave both these classes in one, but this would result in a huge class.

But since I doubt that I am the first one running into this problem, I assume that there exists a more or less canned solution to this I haven't found yet.

7
  • You might make (or use, if one already exist) some specialized C++ code generator suited for your task. Having e.g. a gigantic switch statement is not necessarily harmful if that code is generated. Sep 10, 2014 at 19:34
  • Why is it that you were able to factor out side-effecting operations from the state machine for sending/receiving but you can't do the same for the timer reset?
    – Doval
    Sep 10, 2014 at 19:38
  • @Doval Currently I am setting some bool variables in the statemachine class (like reset_timer = true;) which I then parse in the service class. This does work, but it is ugly in my opinion. Sep 10, 2014 at 19:43
  • 1
    Yet another way to do it is to factor out an object that contains service class data that the statemachine class touches. Now the statemachine class can know about this object, and the service class can know about this object, with no friendship relationship needed. You can call it something like servicestate.
    – btilly
    Sep 10, 2014 at 23:31
  • 1
    Is there any chance you can get your employer to junk the protocol specification and START OVER??? Alternatively, out of morbid curiosity, what protocol is this, and where can I find the protocol specification? Sep 11, 2014 at 0:28

2 Answers 2

2

The classic approach for decoupling two components is by defining a clear interface between them and let them communicate only by this interface (opposed to giving direct access to any internals).

So in your case: create an interface class (in C++ typically an abstract base class) for your service class, defining the interface you want to make public. Any access by the state machine or the 28 functions should be done only through this interface. So the state machine and the service class become decoupled, you now can easily replace it by a mock implementation for testing purposes, if you like.

This works the other way round as well: if your service class needs to access the state machine, define a public interface for your state machine, and access the state machine from outside only through this interface.

4

I think the problem is that your state machine class is too specific for the protocol. If it was generic, the table of actions would be provided by the protocol class to the state machine class. Those actions would just be std::function<void(ServiceClass*).

Clearly the protocol class has access to the service class, as the protocol defines which service functions are called when.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.