dimanche 30 juillet 2017

Code design: objects depending on one another and short-lived composite objects

I am working on a piece of software and am trying to solve a particular problem in an elegant way. I was hoping to get a bit of input to improve my code.

I am trying to calculate a report. The report contains a number of fields. Some of the fields depend on other fields. E.g., one might be the sum of other fields.

Each field has its own algorithm and is defined by a class deriving from a base class ReportFieldBase. The fields are displayed in a hierarchy (composite pattern).

The problem is that some of the fields require the results of certain simulations. A field might require multiple simulations, and each simulation might be used by multiple fields. The simulations are so large that they cannot all be kept in memory simultaneously. Furthermore, each simulation should only be performed once for performance reasons. A simulation is defined by a set of parameters (SimulationParameters).

How can I solve this problem elegantly? The current state of my code looks similar to this:

MustInherit Class ReportFieldCachedBase
Inherits ReportFieldBase
Sub CalculateAndCacheValue()
...
End Class

Interface ISimulationField
Readonly Property SetsOfSimulationParameters() As IEnumerable(Of SimulationParameters)
ReadOnly Property DependsOnSimulationFields() As IEnumerable(Of ISimulationField)
Property SimulationHolder() As IEnumerable(Of Simulation)
Sub CalculateAndCacheValue()
End Interface

The fields that need simulations would now inherit from ReportFieldCachedBase and implement ISimulationField, and define the SetsOfSimulationParameters() for the simulations that they need at runtime. Before filling the report, all ISimulationFields will be calculated and cached:

Sub CacheSimulationFields()
' Algorithm to perform the simulations and cache the corresponding values iteratively. Due to the interdependence, in each iteration a number of
' simulations will be performed and all fields will be calculated that use any of these simulations.
...
' For each iteration:
' - Determine all fields and all simulations that are to be calculated in this iteration.
' - Fill the SimulationHolder() for each of the fields.
' - Call CalculateAndCacheValue() for each of the fields
End Sub

The design feels weird. E.g., any of the ISimulationFields can only be called after the SimulationHolder() has been filled from the outside. This is very error-prone. But I have no idea for a better design. Any suggestions?

Aucun commentaire:

Enregistrer un commentaire