Design Problem: Dealing with multiple time frames

Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved

Join Date: Aug 2008
Posts: 5
Reputation: Gentile is an unknown quantity at this point 
Solved Threads: 0
Gentile Gentile is offline Offline
Newbie Poster

Design Problem: Dealing with multiple time frames

 
0
  #1
Aug 28th, 2008
I am trying to come up with a good class design to deal with asynchronous data to be stored and analyzed over multiple time frames.

I obtain data elements from an asynchronous data source (i.e. the data arrives at irregular time intervals) and wish to place them in a container of fixed length in time, which I call a "DataChart". This will be implemented using a deque. As a new data element arrives from the source, I remove all elements that are, say, 10mins older than the new data element from the back of the deque before pushing the new element on the front. This "10min DataChart" is my shortest time frame.

When the deque fills and the oldest DataElement is 10mins old and is about to be discarded as a new element arrives, I take a snapshot of the deque by averaging over its contents, creating a 10min_AverageElement and storing this average in another container of fixed width in time, a 1day_AveragesChart which is implemented as a deque of 10min_AverageElements. Every 10mins the entire contents of the shortest timeframe, 10min_DataChart, are renewed and thus a new 10min_AverageElement is generated to be stored in the 1day_AveragesChart.

Likewise, I have a 1month_AveragesChart containing 1day_AverageElements made by averaging over the 1day_AveragesChart of 10min_AverageElements when its contents are renewed once a day, and so on.

In this way, I can have any number of time frames spanning arbitrary lengths in time, the shortest will always be a DataChart comprised of DataElements, and subsequent time frames will be AveragesCharts comprised of AverageElements, every chart overflows into a chart of a longer time frame when it fills.

So far, I have a base class Chart which is the interface, and two derived classes DataChart and AveragesChart, each of which contain a deque to store the data or averages elements respectively, and methods to add new data, etc.

So here are my questions.

(1) I have a pure virtual method addelement() in the base class, Chart, to update a given chart with new data. The overloaded addelement() in the derived DataChart takes DataElements, does some validation and adds the elements to the DataChart.

By contrast, addelement() in the derived AveragesChart takes AveragesCharts. It constructs an AverageElement from the supplied (short-timeframe) AverageChart and adds it to the longer timeframe AveragesChart to which it belongs. This is my first problem. addelement should be part of the Chart base class interface, I can't see a way to do that. It could be that I should delegate certain responsibilities of addelement to other methods in the chart, or I could use a visitor, I'm not sure what is the best solution. I don't really want to make a base class "Element" to shoehorn derived DataElement and AverageElement objects into the base class addelement() method for reasons explained in this thread. Your thoughts on this?

(2) Later, I'd like to compute other derived quantities from the charts, like a discrete Fourier transform, for example. I can add methods begin() and end() to the chart interface which return iterators to the Deques they contain and use those iterators in computations. I can also use the iterators to calculate the averages of one time frame needed to make AverageElements of a longer time frame chart. Do you think this is a good idea? Does it expose my implementation of the Charts?
I suppose one could again use a visitor here, or pass function objects to the charts containing the algorithm to be computed on the elements. I'm not sure what the design of that should be yet. Is that a good, extensible design?

(3) In the end, a data element comes in and then the charts will have to be updated, sometimes this will entail overflowing to a longer time frame chart as a shorter time frame fills as mentioned above. I was thinking of writing a class ChartSet which will be contain all the charts, to which I delegate the responsibility of managing the charts. Which class do you think should have the responsibility of generating an AverageElement for the longer time frame Chart when a shorter time frame Chart fills, the ChartSet object which encapsulates the Charts, or the Charts themselves?


Any other comments would be greatly appreciated. My apologies for such a long post. I'm not sure how to abridge it without making things too abstract.
Last edited by Gentile; Aug 28th, 2008 at 11:24 am.
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,089
Reputation: vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all 
Solved Threads: 164
vijayan121 vijayan121 is offline Offline
Veteran Poster

Re: Design Problem: Dealing with multiple time frames

 
0
  #2
Aug 28th, 2008
if you absolutely need a base class Chart (with virtual functions), a hack would be to overload the AddElement function.

i would prefer using templates for your containers as suggested by Narue in the other thread. and as for this issue:
> ... generic template<class T> container and have a method addelement(T& elt)
> but the implemebtation of addelement() depends on the element being added
template specialization would address the problem.
  1. #include <stdexcept>
  2.  
  3. struct DataElement { /* ... */ };
  4. struct AverageElement { /* ... */ };
  5.  
  6. #ifdef INHERIT
  7.  
  8. struct Chart // base class
  9. {
  10. virtual void AddElement( const DataElement& ) = 0 ;
  11. virtual void AddElement( const AverageElement& ) = 0 ;
  12. // other (pure) virtual functions
  13. };
  14.  
  15. struct DataChart : Chart
  16. {
  17. virtual void AddElement( const DataElement& )
  18. { /* add DataElement */ }
  19.  
  20. virtual void AddElement( const AverageElement& )
  21. { throw std::logic_error("incorrect element type") ; }
  22.  
  23. // other overrides etc.
  24. };
  25.  
  26. struct AveragesChart : Chart
  27. {
  28. virtual void AddElement( const DataElement& )
  29. { throw std::logic_error("incorrect element type") ; }
  30.  
  31. virtual void AddElement( const AverageElement& )
  32. { /* add AverageElement */ }
  33.  
  34. // other overrides etc.
  35. };
  36.  
  37. #else // GENERIC
  38.  
  39. template< typename T > struct chart_base
  40. {
  41. // common stuff goes here
  42. };
  43.  
  44. template< typename T > struct chart ; // generalization
  45.  
  46. // specialization
  47. template<> struct chart<DataElement> : chart_base<DataElement>
  48. {
  49. void addelement( const DataElement& ) ;
  50. // other DataChart specific stuff
  51. };
  52.  
  53. // specialization
  54. template<> struct chart<AverageElement> : chart_base<AverageElement>
  55. {
  56. void AddElement( const AverageElement& ) ;
  57. // other AverageChart specific stuff
  58. };
  59.  
  60. typedef chart<DataElement> DataChart ;
  61. typedef chart<AverageElement> AverageChart ;
  62.  
  63. #endif // INHERIT

> I suppose one could again use a visitor here, or pass function objects
> to the charts containing the algorithm to be computed on the elements.
i guess, vistor if your chart is object-oriented, function object if it is generic.

> Which class do you think should have the responsibility of generating
> an AverageElement for the longer time frame Chart
> the ChartSet object or the Charts themselves?
perhaps an element of personal taste here. i think i would let the Charts themselves generate this if all the required information is available within a single Chart; the ChartSet otherwise.
Reply With Quote Quick reply to this message  
Join Date: Aug 2008
Posts: 5
Reputation: Gentile is an unknown quantity at this point 
Solved Threads: 0
Gentile Gentile is offline Offline
Newbie Poster

Re: Design Problem: Dealing with multiple time frames

 
0
  #3
Aug 28th, 2008
I was not familiar with this particular way of using templates. Thank you very much.
Does it make sense to write a virtual method in the templated base class in order to force derived classes to have an appropriate addelement() method? Something like this:
  1. template< typename T > class chart_base
  2. {
  3. virtual void addelement( const T& ) = 0;
  4. };

Obviously the first method would lead to a maintenance nightmare; as more chart types are added, more overloaded addelement() placeholders need to be added to the base and every subclass.
Last edited by Gentile; Aug 28th, 2008 at 1:05 pm.
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,089
Reputation: vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all 
Solved Threads: 164
vijayan121 vijayan121 is offline Offline
Veteran Poster

Re: Design Problem: Dealing with multiple time frames

 
0
  #4
Aug 28th, 2008
> Does it make sense to write a virtual method in the templated base class
> in order to force derived classes to have an appropriate addelement() method?
no. the polymorphism provided by templates is compile-time polymorphism; if you need an addelement() in a class and the class does not provide it, it will be caught at compile-time.

> first method would lead to a maintenance nightmare;
> as more chart types are added, more overloaded addelement() placeholders need to be added
true.
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:



Other Threads in the C++ Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC