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 (i.e. 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 and store this average in another container of fixed width in time, a "1 day AveragesChart" which is implemented as a deque of 10min-AverageElements. Every 10mins the contents of the shortest timeframe, 10min-DataChart, are renewed and thus a new 10min-average element is generated to be stored in the 1-day-chart AveragesChart.
Likewise, I have a 1 month chart containing "1-day averages" made by averaging over the 1-day chart of 10min-averages when its contents are renewed once a day, and so on.
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 and methods to add new data, etc.
Then I have a class ChartSet which holds all the charts, namely, the 10-min DataChart, the 1-day AveragesChart, the 1-month AveragesChart, etc, in its vector of Chart base handles.
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 AveragesCharts comprised of AverageElements.
So here are my questions,
- 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. By contrast, addelement() in the derived AveragesChart takes AverageElements. This is my first dilema.
I could make a base class "Element" to shoehorn derived DataElement and AverageElement objects into the base class addelement() method which can now just take generic Elements. But a DataElement and AverageElement objects are fundamentally different so I'd like to avoid this, plus I'd have to rewrite other portions related to the elements themselves, etc. It would be great if I could overload the base class pure virtual function like addelement(void) in a derived class as addelement(DataElement& data) but then the compiler complains that I haven't supplied an implementation of addelement(void) in derived classes. Your thoughts on this? - Later, I'd like to compute other 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. Do you think this is a good idea? Does it expose my implementation of the Charts?
Another way would be to have something like a visitor, 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? - Which class do you think should have the responsibility of generating anAverageElement for the longer timeframe 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.