Some time ago, I had the the need to find out how a particular variable ended up having the value it had. The application involved was far too large to consider stepping through it, and there were just far too many other values that were added and subtracted for me to consider setting breakpoints on them all. Besides, ultimately, what I wanted to do was track down one particular value that was being added in and find out where it came from.
What I needed was a way to see what variables and values had been used to calculate the target variable’s values and be able to drill down into those variables to find the ultimate source of the number I was after. But that was something that didn’t exist. Variables don’t remember how they arrived at holding a particular value, just what value they currently hold.
I set out to change that and ended up creating the tdecimal
class. In my particular case, the variable type used throughout the system to represent monetary values was decimal
. The t
stands for tracable
and was chosen because it makes it easy change a variable type by simply adding a single letter to the declaration.
Below, I will present some images showing tdecimal
in use, so that, hopefully, the usefulness of this class can be seen. To keep the size of the posts to a reasonable size, I will post the code for tdecimal
in a subsequent post. After that I will post some explanations of how it can be used and why it is set up the way it is.
Before I begin, I just want to say that I know that a lot of what is currently in the tdecimal
class will be much easier to accomplish in .NET 4.5. I wanted to post the code in its current form so that I would have a record of the logic I used in developing it.
The following image shows a tdecimal
value in use and how various information from it can be viewed:
In this case, we are looking at the variable SubTotal
. The locals window shows that the current value of the variable is 310.344224
. It is also possible to see that the last operation that occurred was that we added (_operand
) two source values (_sourceValues
) of 341.344224
and 0
. The 0
comes from a value named “TPO_Summary: Total SQS Special” (which represents the variable TotalSQSSpecial
that appears as the last value in the add at line 422). The 341.344224
came from an unnamed value (in fact, this is the result of the 8 additions and subtractions that precede the addition of the TotalSQSSpecial
).
Note that the 310.344224
is itself a tdecimal
, which means that we can drill down into its _sourceValues
and find out what values were used to create it. If we did, we would see the addition of another tdecimal
and TotalAmount
.
TotalSQSSpecial
is a tdecimal
as well, but note that it has no _sourceValues
(indicating that it was never initialized – sloppy, very sloppy).
The _name
is a text value that can be assigned to tdecimal
. It could be the literal name of the variable, or, as seen above, it can be a more descriptive identifier for the value (which can prove useful when many classes and/or methods use the same identifiers for their variables).
Finally, you can see that the 310.344224
was assigned to SubTotal
at line 422 of the in the CalculateTotalOwing method in the source code file TastingPartyOrder.cs (_assignedAt
).
The next image shows a portion of a web page generated by the application. The programmers have the ability to display a table showing the breakdown of any tdecimal
value they wish. In this case, a partial drill-down into the value label “TPO_Summary: Total Owing” is shown:
In this image it is possible to see that the “Total Owing” was created by adding 3 values together ($329.58+$23.35+$0.00). One of the values (TPO_Summary: SubTotal) is further broken down to show that it is derived from the addition of 3 values ($262.48+$67.10+$0.00). And so on.
By clicking on the small + and – icons, any tdecimal
value can be expanded to see how it was derived.
Additionally, not shown above, is when the mouse is placed over any of the lines, the _assignedAt
text is shown in a tooltip, so it is possible to see in what file and at what line a value was assigned.
This tool has proved indispensable to to me in tracking down bugs or explaining system generated values. Our application is a business app, so it rarely does anything more complicated than dividing 2 numbers, but it is a relatively large application. Tracking down why a particular value is $67.19 and not $67.18 can be an arduous task without a tool like tdecimal
.
In the next post I will present the code for tdecimal
and for the table display shown above. I know you may have some questions as to why tdecimal
shows its values the way it does. I hope to make all that clear in a subsequent post.