The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Generic Data Structure with Application Specific Data Question

I have created a generic data structure which holds data of some class. There are two parts to my project, (a two tier project sorda) One part of the project uses the data-structure and understands the structure. This part of the application hands the data contained within the strcuture to the second tier of the application. I was doing this in hopes that the Second tier would not need to know anything about the data structure itself.

the first tier provides available data to the second tier, and when the second tier is done with it, it reports that the it is done with the data.

however to do this, i ended up having to use a hashtable to map the datastructure node to the data object. (the datastructure node actually contains a reference to the data object) but the data object does not contain a reference to the node. The map was neccesary so that when the second tier reports the data object back, it knows which node it is associated with it.

is there a better solution to this problem? do i need to make a bi-directional reference? or do i just need to pass the node itself to the second tier and forget about this crazy indirection to keep the second tier oblivious from the data structure (which is much like a graph)
yonfon Send private email
Monday, December 03, 2007
 
 
The answer to this question depends on the details.  What language are you using?  How do you want to use the structure generically in phase two?

Please provide some detail.
Andrew Bell Send private email
Monday, December 03, 2007
 
 
First things first, language is java. I don’t want to really use the data structure in the second phase. The data structure (which is much like a graph) nodes have references to an attribute “data”, which is of type Object. The first phase, provides information on how move through the data structure. The state of the iterator of the data structure at any given time is 0 ore more elements, so it is not a standard iterator, because it may provide several nodes at a time. It is the job of the first phase to know how the data structure works so it knows about the application specific details and the data structure details. It is also the job of the first phase to supply the “data” to the second phase, in which the second phase can pick the “data” Object it needs. When the second phase gets done with the “data” object, it tells the first phase it is done with it, and the iterator changes state.

The problem is this, the “iterator” changes state based on the data structure node. So, to change the state of the iterator, I have a function which processes the Data Structure Node: processNode(Node node);

When the second phase is done with the Data, it calls a function of the first phase,
Say the function is called finishedWithData()

finishedWithData(AppData data)
{
    // translates AppData to its Node counter part
    processNode(nodedata_map.get(data));
}

Where nodedata_map is a map between AppData and Node.
Is this to much engineering? Or too much effort? Should I just pass Node to the second tier? And use node.getData() in the second phase? The reason I was doing this, was because I may be changing the underlying data structure later on, and I didnt want have to change a lot of code in the second tier if I needed(had) too.
yonfon Send private email
Monday, December 03, 2007
 
 
Again,

More detail is needed (code would help).

In general, though, it seems that you have made things more complicated than necessary.  If you aren't worried about separating the first and second phases with threads, just call the function in the second phase from the first (passing whatever is necessary) and wait for it to complete, at which time you can iterate.

If you do care about separating the first and second phases (separate threads) then you should probably separate the two with some sort of a queue (or two - one for first->second communication and one for second->first communication).
Andrew Bell Send private email
Monday, December 03, 2007
 
 
I find the example long and tedious to represent so I will try, I am not concerned about seperating the phases between threads, they share the same thread.

This is incomplete of course, class Project is much like a Facade, the ultimate goal is that my Agents dont have to work with the Network Data Structure. Like you said, this ends up being way to complicated, and it would probably be best just to pass my Nodes to the agents.

However, it makes sense in someways, because now I can change the underneath data structure without worrying about my agent code (my project manager) I agree its ugly and can be much simplified

class Project
{

  Plan project_plan; // is my iterator
  Network network; // is my datastructure
  Hashtable node_requirement_map<Requirement, Node>; // map

  ....

  Project()
  {
    network = new network();
    plan = new plan(network);

    findRequirements();
  }

  ArrayList<Requirement> getAvailableRequirements()
  {
    //returns Requirements that not have been assigned
    //using the map
  }

 
  processRequirement(Requirement requirement)
  {
  plan.processNode(node_requirement_map.get(requirement));
  node_requirement_map.remove(requirement);
  findRequirements();
  }

  assignRequirement(Requirement requirement, Agent agent)
  {
    //assigns agent to requiremens
  } 

  findRequirements()
  {
  //Pseudocode
  //
  //for each available node of plan.getAvailableNodes()
  //node_requirement_map.put( 
      (Requirement)node.getData(),node);
  }

}

Interface IPlan
{
  //moves the plan along
  processNode(Node node);            
  //returns a list of available nodes
  ArrayList<Node> getAvailableNodes();    
}

ProjectManager extends Agent
{
    Project project;

    public step()
    {    
        if(project.hasRequirements())
            assignRequirements();
    }

    public assignRequirements()
    {
        if(agents are available)
          project.assign(requirement,agent);
    }

    public completeRequirement()
    {
        project.processRequirement(Requirement);
    }
}
yonfon Send private email
Monday, December 03, 2007
 
 
Why not program the second phase against an interface that contains a getData() method on it?  Then you can just pass an object to the second phase that can get to the data somehow and you'll be able to change your implementation.

public interface INodeDataProvider {
  object getData();
}

public class Node : INodeDataProvider {
  public object getData() {
    // get node data
  }
}

or you could use a wrapper, that contains the data, and the node so you can get the node back from the object when its passed back to you.

public class NodeWrapper : INodeDataProvider {
  public object getData() {
  }

  public Node getNode() {
  }
}
Ted Elliott Send private email
Tuesday, December 04, 2007
 
 
Ted, Thanks for the suggestion, that is what I will do

I believe I over-engineered the problem, the more I think about it anyways ... Thanks for everyones help! Of course if you all think of anymore cool ideas
yonfon Send private email
Tuesday, December 04, 2007
 
 
This seems like it falls into the category of "mid-tier data cache". If so, consider http://jakarta.apache.org/jcs/.

It would be a shame to write something that already exists!

Let me know if I'm missing the point ... now, I'm curious.
Patrick Foley Send private email
Friday, December 14, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz