What is the Best way to couple data among FSM design pattern objects -

Recommended Posts

Hi,  I have a question related to FSM design which uses commands as well. Please guide.

What is the Best way to couple data among FSM design pattern objects (Session, State, ReportGeneration objects.)- 

I have a class called StateEngine which get a request to permorm some action
to permorm that action it creates a session class object and sets up the context 
for States and Commands objects.

Here each State runs one or more commands and generate result for that perticular state.
That State object saves thaose result in the Session class object(Context).
Which is later on used to generate report.

I have question what could be the best way to couple data between Session(Context), State and the reportGeneration Logic?
Few thoughts comming to me are- 
1)- Pass a long list of data structures class Session data(lists..., maps...) to ReportGeneration class object by reference
    (long list to parameters sharing).
    
2)-    Declare class ReportGeneration friend to class Session so that it can have access to all it 
    data structures(request, each command procession results) to generate detailed report. 
    friend is a bit violation to encapsulation(but seems to me a bit good choice).
3)- By using accessors in Session class and passing Session reference or pointer to ReportGeneration class.
    (which need too many accessors and may tend to make class huge and  complex.).

below is the code to give some idea what I want to achieve.

Note:  I made State friend to Session class is there any better way I can achieve encapsulation.
        Please Suggest.

class SateEngine
{
    public:
        // It creates a new session for each action to be performed.
        // here each action can have n(1...n) States and each State can have n Commands(1...n).
        startState(string action );
};

class Session
{
    public:
        Session(string action);
        // from action deduce all States and excute the one by one end state is NULL. 
        Request* decodeRequest(string request);
        
        void startStateExecution();
        
        // Transition to nextState if present else return NULL.
        State* nextState();
        
        
        void logResponse();
    private: 
        string request;
        Request DecodedReq;
        map<string, string> resMap;   // specific value used for reportGeneration
        map<string, Command> commandsData;
        list<Result*> sessionResult;
        list<Command*> sessionCommands; // for debugging purpose reportGeneration
        list<States*> sessionStates; // for debugging purpose reportGeneration
        
        friend State; //// State class is friend to Session(Context) so it can update session private data.
        friend Summary;
};

class State
{
    public:
        Sate(Session *session)
        addCommands();
        processionCommandResult();
        saveToSession(); // saves values to sessions private data.
        State* nextState();
        void generateReport( Session *session);   // if next state is NULL;
};

class Command
{
    public:
        void executeCommand;
        void prepareResult();
        
    private:
        list<CommandResp> result;
};

class Summary
{
    // uses all data structures save in Session generate summary
    void prepareResponse( string& response) = 0; 
};

class FinalresultSummary: public Summary
{    };

class FinalDetailedresultSummary: public Summary
{    };

Share this post


Link to post
Share on other sites
20 hours ago, AnuragD said:

what could be the best way to couple data between Session(Context), State and the reportGeneration Logic?

The best is to not couple them at all, I believe.

You also have code marked as a friend class.  In C++, typing the word "friend" is nearly always the wrong approach. 

Looking it over, report generation like you describe is often best done with the visitor pattern. Your current design uses an object that peeks inside every other object to look at what is inside. It won't work well as code expands. Your reporting class would need to be updated every time a Session or State type is modified. It would need to be adjusted any time someone extended either a Session or a State. So instead of having one object that knows everything about all other objects and peeks inside them, prepare something that visits each of the objects.

The wikipedia article describing it is rather abstract, so making it more specific.  Make an object, perhaps called a ReportGenerator, which you will pass around everywhere, it will visit every object in the hierarchy, and as it visits each object it generates the report as it goes.  Create a ReportGenerator object and send it to the State Engine to fill out.  The State Engine can then pass the ReportGenerator, which can add whatever information it needs about itself, then pass it on to each State to fill out.  Each State object can add whatever information about itself, then pass it on to each Session object to fill out.  The Session object can add whatever information about itself, then pass it on to each Context object to fill out.  The Context object can add whatever information about itself, pass it on to sub-objects if necessary, and be done.  When it finishes, the ReportGenerator has visited all the objects in the hierarchy and collected everything it needs to generate its report.

 

Share this post


Link to post
Share on other sites
12 hours ago, frob said:

Hi Frob,

Thanks for the valuable input. It seems to me the best way getting rid of friend relationship with class State and ReportGenarator.

Regards,

Anurag 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now