1

I have a class that contains some members that may be modified from external sources:

class CNode
{
protected:
    // these members might be changed by users   
    std::string m_sName;
    CState m_CurrentState;
    CColor m_DiffuseColor; 
};

The sample is simplified, it has more members in my code.

Now what would be the best practice to change

  1. single
  2. multiple (at once)
  3. all members (at once)

of this class?

My code needs to handle all cases, though internally case 1. will be the usual case. Most of the time it is applied to a single CNode but it might also be applied to an array of nodes.

I know two possible solutions that both don't really satisfy me:

  1. set&get for every variable:
    Pro:
    Every variable is modifiable independently from other members.
    Easy to set the same value for multiple CNodes.
    Contra:
    A lot of set&gets;
    If a new variable is added, a new set&get needs to be added as well.

This would work best if one Variable is changed in many CNodes

  1. Create a CProperties class that contains all modifiable variables:
    Pro:
    One set&get in the parent class - properties may be added/removed without needing to modify set&get.
    This also reduces the amount of methods in my API that processes user input.
    Contra:
    setting individual variables requires getting the current CProperties, so the other values won't be modified.

This would work best if multiple/all variables are updated at once in a single CNode.

Like so:

class CProperties
{
    // these members might be changed by users   
    std::string m_sName;
    CState m_CurrentState;
    CColor m_DiffuseColor; 
}

class CNode
{
public:
    const CProperties* GetProperties();
    void SetProperties(CProperties*);

protected:
    CProperties m_Properties;
}

This would be the most lazy version (by code creation effort) but also the most obnoxious version for me, since setting single variables requires getting the current properties first, modifying a single variable and then setting the complete properties class back to the node.
Especially in the modify-a-single-variable-in-multiple-CNodes-case this seems to be an awful solution.

Time of execution and (size) overhead is mostly irrelevant in my case. (Which would really be my only good argument against the lazy version)
Instead I'm looking for clean, understandable, usable code.

I could think of a third possible solution with a dynamic approach:
One set method has an object as parameter that may contain one or more values that need to be modified. The API then only has one set method that won't need any modification if the CProperties change. Instead a parsing method would be needed in the CNode class. This parsing method would still need to be updated for every change in the CProperties, though I'm confident this should also be solvable with the compiler through templates.

My question is:
Are there any other possible solutions for my use case?
Which approach is the most sensible one?

Tomas Dittmann
  • 424
  • 7
  • 18

1 Answers1

0

You can add the logic of how to update and what to update into the class and only provide it with a source of information.

Look at how you build the properties object and transfer the logic into an update function that will reside in CNode.

If CNode needs external sources of information in order to perform the update then transfer them to the update function.

Preferably the number of arguments passed to the update function will be smaller than the number of fields in CNode.(Ideally zero or one)

CNode will only update the fields that have actually been modified.

No need for a multiple set functions, uniform way of updating class, no information getting lost between the cracks.

Jonathan
  • 552
  • 1
  • 4
  • 10
  • Thanks for the hint! I also thought of adding an update flag into the property class that would specify which values should be updated. This information would immediately become irrelevant after the update so I didn't want to add it. But I didn't think of using it as a parameter yet. – Tomas Dittmann Jan 20 '16 at 13:01
  • Just to clarify I meant an update function as in: void CNode::Update(); which will update the CNode correctly give the required information needed to update the class. – Jonathan Jan 20 '16 at 13:05
  • The informationen needed to update the class are coming completely from external sources. So I would need to transfer the updated CProperties as well as what was updated within the CProperties to CNode::Update(). However, with this way at least the request of the previous CProperties will become unnecessary. – Tomas Dittmann Jan 20 '16 at 13:15
  • You don't need CProperties, pass into the update function the external sources and allow the function to query the updated state of the CNode. This is under the assumption that the number of external sources is smaller than the number of the CNode fields. – Jonathan Jan 20 '16 at 13:22
  • Ok now I understood your Solution, however that will not be possible. The updated data comes from a dialog (kind of) that is in another project where the Library with the CNode is included. This dialog has some fields and dropdowns where a user can change values. On change an event is fired that reads the value and sends it to the node. It should not be necessary to give the node access to the dialog members. – Tomas Dittmann Jan 20 '16 at 13:24
  • I assume the data is not specific to a single CNode meaning the user doesn't choose a color for a single CNode(for example). If that is the case then you can store the settings the user entered in the dialog inside a settings class when the change event is triggered and pass the updated settings class to the update function of the CNode class. Maybe I'm missing something, In my perspective the CNode represents data in the memory and the dialog represents user data which is for the most part stored elsewhere and does not exist solely in memory. Anyhow, best of luck with your project. – Jonathan Jan 20 '16 at 13:51
  • I think Dialog was the wrong name, they're called Panes in MFC. sorry for the confusion! - There are many Nodes. The user may select a Node. then the dialog displays the current node's values. The user may also select multiple nodes. In both cases the user then can change colors/names etc. The values are stored in CMFCPropertyGridProperties which fire said event when they've been changed. I just can't push the whole pane into the CNode. This was never object of the issue here. You pushed me into the right direction. Thanks again! – Tomas Dittmann Jan 20 '16 at 14:15