0

I am trying to implement a tree data structure that callers of my code edit for me to operate on. The idea is that the caller can hold a reference to nodes from the tree and modify their data (both attributes and children), which triggers an event that prompts my code to update a visual render of the tree.

The problem that I have is that each node also needs to hold some private data (a reference to the corresponding visual element) which I don't want to have polluting the public interface of the node object. The private data needs to be accessible by the main class that is handling the tree object.

I could decide to just stick the private data onto my public interface like this:

class Node
{
    public int NodeData;
    public List<Node> ChildNodes;

    public object PrivateVisualizationData;
}

class TreeControl
{
    public Node RootNode;

    // Use "PrivateVisualizationData" fields on node objects
}

However, this presents two problems as I see it:

  1. Any consumers of Node will see the PrivateVisualizationData field, which could be confusing
  2. External code could modify my private data, breaking code that needs it

How could I design this structure so that each node has custom data associated with it, but the data isn't accessible externally? I would like to avoid the management cost of a separate lookup table if possible, but that may be what I end up doing.

6
  • 1
    So you need PrivateVisualizationData to be both accessible and not accessible? Commented Aug 18, 2016 at 11:34
  • the internal keyword comes to mind. That, or accessing protected members from a base class.
    – MetaFight
    Commented Aug 18, 2016 at 11:37
  • Whan language is that? Java I presume.stackoverflow.com/questions/20921365/… Commented Aug 18, 2016 at 11:49
  • What exactly do you consider "the management cost of a separate lookup table"? Are you worried about performance or that development will be to hard to do? If each node has an identity (some unique ID) looking up your private info would be trivial in a hashtable. Commented Aug 18, 2016 at 12:00
  • @TulainsCórdova @MetaFight So you need PrivateVisualizationData to be both accessible and not accessible? Yes. Whan language is that? Java I presume. It's C#, but it mostly doesn't make a difference. Marking the field as internal might work though.
    – Wasabi Fan
    Commented Aug 18, 2016 at 19:01

2 Answers 2

1

You could try something like this:

    class Node
    {
        public int NodeData;
        public List<Node> ChildNodes;
    }

    class TreeControlNode extends Node
    {
        public object PrivateVisualizationData;
    }

    class TreeControl
    {
        private TreeControlNode RootNode;
        public Node GetRootNode()
        {
            return (Node)RootNode;
        }

        // Use "PrivateVisualizationData" fields on node objects
    }

Inheriting from the Node class allows you to use all of the members and methods of Node while still adding your special data. By returning your "RootNode" as the Node class the user should only us the Node members and methods.

3
  • OP will end up having the same problem. Any consumers of (now) TreeControlNode will see the PrivateVisualizationData field. Also "The private data needs to be accessible by the main class that is handling the tree object.". Commented Aug 18, 2016 at 14:22
  • That's true, but the point of TreeControl returning just a Node means that consumers using Node to modify the underlying tree maintained by TreeControl will only see NodeData and ChildNodes when working with the node. Commented Aug 18, 2016 at 17:48
  • I like this. The main issue that I have is that a caller could theoretically create a class implementing Node and add an instance of their class to my tree, and I would have no way of stopping it. I could probably just ignore nodes which aren't of the right type, but that introduces the possibility of silently failing because a caller didn't understand the API. Another option would be to create my own Add/Remove methods, but then I would be preventing use of the language's collection features.
    – Wasabi Fan
    Commented Aug 18, 2016 at 19:18
0

Your best bet is probably to provide some additional metadata for the members that you do not want to display:

class Node
{
    public int NodeData;
    public List<Node> ChildNodes;

    [Hide]
    public object PrivateVisualizationData;
}

Your UI code can then check for the presence of the [Hide] attribute, and inhibit display.

If your UI is on the other object, then this is really no different from the usual separation of concerns that accompanies, say, an MVVM project. Your class that represents the UI object is the ViewModel; you would simply copy those elements that apply from your domain object (TreeControl) into your ViewModel, and only those fields get displayed.

6
  • When OP says says he is worried that "Any consumers of Node will see the PrivateVisualizationData field..." I think he's thinking about client code, not necessarily final users through a UI. Commented Aug 18, 2016 at 16:22
  • Then he needs another collection that isn't exposed. I assumed that, when he was talking about "visual elements," he was referring to UI. Commented Aug 18, 2016 at 16:26
  • Yes, this isn't exactly what I was looking for. Sorry if I wasn't clear; I updated the question to highlight the big point.
    – Wasabi Fan
    Commented Aug 18, 2016 at 19:20
  • @WasabiFan: A member can't be public and private at the same time. You'll either have to store the private data somewhere else, or use a boundary access modifier like private or internal to segregate your data. Commented Aug 18, 2016 at 19:27
  • @RobertHarvey Not necessarily. The goal is just to hide the "private" data from consumers; it isn't required to make it completely inaccessible to other code as long as it isn't easy to mess it up. So, for example, if my code only ever returned nodes by their Node interface type, the concrete class implementation pf Node could be the one that holds the private data while the consumer only sees the interface's fields. If I defined that concrete implementation within my manager class and made it private, the only way for a consumer to see the special data field would be through reflection.
    – Wasabi Fan
    Commented Aug 18, 2016 at 19:34

Your Answer

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

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