Note that there are some explanatory texts on larger screens.

plurals
  1. PODesign Pattern to track partial results of a complex process
    text
    copied!<p>I'm facing a programming problem that I don't know how to solve in a <strong>object oriented</strong> and <strong>flexible</strong> way. I have in mind some bad solutions, but I'm searching for a good one. I develop in Java, so I prefer Java ideas, but any object oriented idea is welcome.</p> <p>I've been searching for ideas, design patterns, or some algorithm that can help me, but I don't know which terminology or name give to my problem, so I couldn't find any clue.</p> <p><strong>Problem:</strong></p> <p><em>Summary:</em></p> <p>I need to track partial results of a process that makes different changes to a collection of entities. I need this to report to the user, the detail of each calculation "step" in a table report. And also I need to persist this collection in a database.</p> <p><em>Detail:</em></p> <p>The software I maintain has an entity similar to this one:</p> <pre><code>public class Salary { private Date date; private BigDecimal amount; } </code></pre> <p>That is grouped in a Collection, like this:</p> <pre><code>List&lt;Salary&gt; thisYearSalaries; </code></pre> <p>This set of entities can be modified by a set of "tasks" depending on some rules:</p> <ul> <li>Apply a certain tax (from a set of differents taxes)</li> <li>Calculate a Future value for the money amount (<a href="http://en.wikipedia.org/wiki/Future_value" rel="noreferrer">More Info</a>)</li> <li>Discount an amount of money to keep below a maximum</li> <li>etc...</li> </ul> <p>For example:</p> <pre><code>public void processSalaries(List&lt;Salary&gt; theSalaries) { applyTax(theSalaries, Taxes.TAX_TYPE_1); (...) getFutureValue(theSalaries, someFutureDate); (...) restrictToAMaximum(theSalaries, Maximum.MARRIED_MAXIMUM); (...) applyTax(theSalaries, TAXES.TAX_TYPE_3); (...) } public void applyTax(List&lt;Salary&gt; theSalaries, Tax taxToApply) { for(Salary aSalary : theSalaries) { aSalary.setAmount(calculateAmountWithTax(aSalary.getAmount(), taxToApply); } } (...) </code></pre> <p>What I need is to process this collection of salaries, making changes to the amount of money but preserving all the intermediate "states" of the money amount, to show it to the user in a table with columns like these:</p> <p><strong>Example Report:</strong> <em>(the question is about the first 4 rows of data only, don't pay attention on the rest)</em></p> <p><a href="http://img198.imageshack.us/img198/5651/ue5l.jpg" rel="noreferrer">Report Example http://img198.imageshack.us/img198/5651/ue5l.jpg</a></p> <p><strong>My Ideas:</strong></p> <p><strong>Add an attribute for each "partial result" on the class Salary</strong></p> <pre><code>public class Salary { (...) private BigDecimal originalAmount; private BigDecimal amountAfterFirstTax; private BigDecimal amountAfterMaximumRestriction; (...) } </code></pre> <p>Problems: </p> <ul> <li>The "steps" aren't rigid, maybe tomorrow one "step" changes, a new one appears, or the "meaning" of some step changes. In that case I will need to refactor the code too much.</li> <li>Some "steps" can be repeated, so, how can I tell to the "method" in which attribute have to "set" the result of the calculation?</li> </ul> <p><strong>Add a HashMap to the Salary class where I can put the partial results, and pass to the "step" method the "key" where it have to put the partial result</strong></p> <pre><code>public class Salary { (...) HashMap&lt;String, BigDecimal&gt; partialResults; (...) } </code></pre> <p>Problems:</p> <ul> <li>In some place I need to populate the HashMap to a JPA entity to save it on my Database</li> <li>If another developer changes the name of the key (for whatever reason) maybe the "populating" of the attributes gets broken</li> </ul> <p><strong>Final Note:</strong> There are other similar situations with other "similar" entities in my application, so it would be great if we can find a general solution for this :D</p> <hr> <p><strong>Edit: New doubts about how to model the data to persist it</strong></p> <p>All the ideas are similar and really useful. All of them are related to the Command Pattern and I think that are great solutions. But now I have some new doubts:</p> <p>With a higher level of abstraction, my application does something like this:</p> <ol> <li>The user enter the list of salaries</li> <li>The app process this salaries through different "steps"</li> <li>With the LAST salaries amount it calculates a mean and continues with other calculations</li> <li>After some screens and some processing, I show a report to the user with the FINAL salaries amount, and all the intermediate steps. And then I save this intermediate information for audit purpose</li> </ol> <p>So, the second step is almost solved. I would use something like the Command Pattern. My problem now is how can I model the data to persist it in a relational database. Because, besides the partial "result" of each operation, there is more information that I don't need to show to the user, but I need to store it in a database.</p> <p>My idea is something like this:</p> <p><strong>Salaries</strong> Table:</p> <pre><code>id date // The date of the Salary finalAmount // The final amount after all the calculations ends </code></pre> <p><strong>partialResults</strong> Table:</p> <pre><code>id salaryId // The id of the salary which this element represent a partial result amount // Partial amount operationCode // Type of operation operationDescription </code></pre> <p>But the problem is, my "future value" operation has, as an output, this information:</p> <ul> <li>Date of the future value</li> <li>Coefficient used for update the value</li> <li>Partial amount</li> </ul> <p>But "apply tax" operation has different information:</p> <ul> <li>% Tax applied</li> <li>Partial Amount</li> </ul> <p>So, how can I save different "output" information for different operations?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload