Coding a flow diagram

skimread

Executive Member
Joined
Oct 18, 2010
Messages
8,486
#1
I need to code a pricing calculation flow diagram in .net (C#). It has inputs and gets outputs on various factors including various taxes based on the item purchases, weight, dimensions, scarcity , distance, type of item, additional taxes, city taxes, leadtime,salesmen commission tables, time of year which can change regularly so will have to be updated regularly.

I can call a bunch of pricing calculations in sequential order and use if statements but because there are so many permutations I don't think even unit testing will cover it all.

What I would prefer rather than writing a long sequential list of steps is if there exists a flow diagram diagram structure in code where I can visualize the pricing calculation and write the relevant coding blocks in the various part of the flow diagram code.

Does anyone know of a design pattern that I can use in my situation or some code that already exists to create flow diagrams.
 

Hamster

Resident Rodent
Joined
Aug 22, 2006
Messages
30,940
#2
but because there are so many permutations I don't think even unit testing will cover it all.
Why not test each of the functions by themselves?

Code:
function addVAT(value) {
    return value * 1.15;
}

function addShipping(value, shippingClass) {
    if shippingClass == 1:
        return value + 20
    return value + 50
}
Surely if you test that addVAT increases 100 to 115 and addShipping increases a value by 20 or 50 it is good enough instead of testing every possible chain combination?

Either way, if you had a CONTEXT object you can pass between functions with a standard signature you can chain them dynamically:

Code:
// assuming a signature of void do(context)
map = {'vat' : addVAT,
       'shipping' : addShipping,
       'fees' : subtractFees}

function addVAT(context) {
    context.value *= 1.15
}
function addShipping(context) {
    if context.shippingClass == 1:
        context.value += 20
    else
        context.value += 50
}
function subtractFees(context) {
    if context.value > 100:
        context.value -= 20
}

function process(context, chain[]) {
   for c in chain:
       map[c](context)
}

// execute
context = new Context()
context.value = 95
chain = ['shipping', 'vat', 'fees']

process(context, chain)
Unless I misunderstood you.
 
Last edited:

skimread

Executive Member
Joined
Oct 18, 2010
Messages
8,486
#3
Yeah that is a sequential process which is how I could do it. I wanted to know if their was a better way.


The requirement can vary greatly as it is per US state which have their own rules.

So US some states have vary different workflow requirements. Some have tax charges per item some only on the total. Some have different fees based if a person is a resident or not. Some I have to send confirmation and wait weeks to get it so I have to store state. Once confirmation is received weeks later then other prices might have changed, even rules might have changed. So I have to remember the state of an application at a time.

It's a government registration workflow that lawyer's use where first step is complete all the registration steps and then get a quote based on various rules. The application starts by sending the documentation to a various state for processing. They take their sweet time and have various rules themselves that change all the time. By the time the registration docs come back from the various states the fees might have increased due to yearly increase or new fees be added. So the delay in waiting for the registration and approval to return from the US state is the issue.
It must also support making manual adjustments at the end since the system for application are paper based and I can't control 100% the final fees application each sate so the flow diagram must allow a manual fees adjustment either a + or a - at the end that must show on the final invoice.

It's a pity that MS decided against writing Windows Workflow in .net core as that would have been ideal for me to use.
 
Last edited:

Hamster

Resident Rodent
Joined
Aug 22, 2006
Messages
30,940
#4
Determining the steps upfront or determining it as each step executes are your only real options as far as approach goes though. If you have to DIY a workflow engine yourself, a record in a table with a status and a step() function that executes after every action (screen input, cron job etc) should suffice.

I've had to do that for one of our processes at work and it works very well. The only thing I added extra (it's a requirement for this process) is a log table. Same fields as the record table and the new record entry is logged there every time the step() function is called. An audit log if you will.

But this is fairly basic stuff which you probably already know.
 

skimread

Executive Member
Joined
Oct 18, 2010
Messages
8,486
#5
Determining the steps upfront or determining it as each step executes are your only real options as far as approach goes though. If you have to DIY a workflow engine yourself, a record in a table with a status and a step() function that executes after every action (screen input, cron job etc) should suffice.

I've had to do that for one of our processes at work and it works very well. The only thing I added extra (it's a requirement for this process) is a log table. Same fields as the record table and the new record entry is logged there every time the step() function is called. An audit log if you will.

But this is fairly basic stuff which you probably already know.
Yes I will probably end up coding a state machine and that is easy to code. A full workflow engine is harder. There are a few github workflow engine projects too but so few people actually use them.
If I look at paid workflow engines they are ridiculously expensive. e.g. https://workflowengine.io/pricing/
I am disappointed Windows Workflow doesn't exist in .net core as it was useful and is also a nice thing to put on the CV to show expertise.
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
5,918
#9
I need to code a pricing calculation flow diagram in .net (C#). It has inputs and gets outputs on various factors including various taxes based on the item purchases, weight, dimensions, scarcity , distance, type of item, additional taxes, city taxes, leadtime,salesmen commission tables, time of year which can change regularly so will have to be updated regularly.

I can call a bunch of pricing calculations in sequential order and use if statements but because there are so many permutations I don't think even unit testing will cover it all.
The "so many" permutations alone should steer you away from a diagram based code generator of sorts.

As mentioned by @Hamster the approach that would offer the greatest degree of flexibility is building out your computations as functions. More specifically, mathematically pure functions that all share a common function signature to making composition easier.

Note:
  • Pure functions can be reduced to a common signature using partial function application and currying.
The goal being to dynamically in process build up a particular permutation by sequencing the lazy computations using a data structure e.g. List, LinkedList, Tree, ...; purpose being to affix the computation order assuming its not a commutative process. The final computation can then be a simple case of either looped execution & aggregation of the functions using Linq, or alternatively compositing all the functions down to a single function that encapsulating the full permutation.

Naturally if the permutations are either more static or frequently re-used; then one should look at memoizing the permutation and/or loading the permutations from configuration.
 
Last edited:

konfab

Honorary Master
Joined
Jun 23, 2008
Messages
20,001
#11
The "so many" permutations alone should steer you away from a diagram based code generator of sorts.

As mentioned by @Hamster the approach that would offer the greatest degree of flexibility is building out your computations as functions. More specifically, mathematically pure functions that all share a common function signature to making composition easier.



The goal being to dynamically in process build up a particular permutation by sequencing the lazy computations using a data structure e.g. List, LinkedList, Tree, ...; purpose being to affix the computation order assuming its not a commutative process. The final computation can then be a simple case of either looped execution & aggregation of the functions using Linq, or alternatively compositing all the functions down to a single function that encapsulating the full permutation.

Naturally if the permutations are either more static or frequently re-used; then one should look at memoizing the permutation and/or loading the permutations from configuration.
I am going to go one further.
I think a functional decomposition is the best way to solve the problem, but he wants an easy way to view how a calculation was calculated such that he can sanity check it. Essentially the application should keep track of the state of the data as it flows through the app.

Fortunately, such software already exists:



https://pycallgraph.readthedocs.io/en/master/examples/basic.html

A little bit of modification to this software to nicely parse the inputs and outputs of each function onto the edges of the graph and he would have a very easy way of seeing how the calculations were done.
 

cguy

Expert Member
Joined
Jan 2, 2013
Messages
4,632
#12
From what you’ve stated in the OP, you could probably go a long way, by just flattening the calculation (removing the if’s), and then populating the non-applicable values in your table with 0’s (e.g., for states with no state taxes) or 1’s (when there is no rate multiplier), etc.

It’s redundant computation of course, but this doesn’t sound like something that would be speed sensitive.
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
5,918
#13
I am going to go one further.
I think a functional decomposition is the best way to solve the problem, but he wants an easy way to view how a calculation was calculated such that he can sanity check it.
That's a visual call trace; which BTW is a built-in with visual studio, for example:
https://docs.microsoft.com/en-us/vi...while-debugging-in-visual-studio?view=vs-2019

... but that's quite different from designing a set of functions to be lifted into a data type for a dynamic composited set of many to many predicated permutations.

As for the visualisation; that's IMO a relatively easy thing to create with something like GraphViz.
 
Top