14

We have an application that has a LOT of mathematical checks on the page and according to it, the user is given a traffic light (Red, green, yellow).

Green = He may continue
Red = Dont let him continue
Yellow = Allow to continue but warn

These formulas operate on the various text-fields on the page. So, for example, if textbox1 has "10" and texbox2 has "30"... The formula might be:
T1 * T2 > 600 ? "GREEN" : "RED"

My question is:
Is it possible to somehow centralize these formulas?

Why do I need it?
Right now, if there is any change in a formula, we have to replicate the change at server-side as well (violation of DRY, difficult to maintain code)

One option could be to
- store the (simple) formula as text with placeholders in a config(?)
- replace the placeholders with values in javascript as well as server-side code
- use eval() for computation in JS
- use tricks outlined here for C#

In this approach issue could be different interpretations of same mathematical string in JS and C#.

Am i making sense or should this question be reported?!! :P

Community
  • 1
  • 1
Ramanpreet Singh
  • 860
  • 2
  • 8
  • 14
  • 1
    sharing server logic and client logic is what Google Web Toolkit tries to solve. – John Dvorak Jan 22 '13 at 10:15
  • 1
    Don't use eval, eval is slow (and evil)! use script interpolation and proper caching. – John Dvorak Jan 22 '13 at 10:15
  • This is generally difficult problem. I suggest not to change formula. :P But seriously, you will probably have to keep formula as a string in database and use some kind of parser. – freakish Jan 22 '13 at 10:16
  • I will check if GWT can help me.... – Ramanpreet Singh Jan 22 '13 at 12:43
  • 2
    How about create a business rules class (server-side) that a client-side AJAX talks to when it need to lookup any type of response? So basically, the math checks will only be stored on the server-side while the client-side just have code that will go to the server for any checks or validation it needs. – Dennis Rongo Jan 22 '13 at 20:45
  • @DennisRongo The answer is same as your comment, just that I liked the way everything was put into perspective by the poster. :) – Ramanpreet Singh Jan 28 '13 at 07:41
  • As for GWT - I *think* it only works for Java. I did not extensively check it out, please correct me if I am wrong. – Ramanpreet Singh Jan 28 '13 at 07:44
  • @user1557032 it's alright, my comment was meant to be suggestive anyways ;) and I wasn't sure enough if it was worth making an actual answer. Glad everything worked out which all that matters to me :). – Dennis Rongo Jan 28 '13 at 07:45

5 Answers5

2

Depending on your application's requirements, it may be acceptable to just do all the validation on the server. Particularly if you have few users or most of them are on a reasonably fast intranet, you can "waste" some network calls to save yourself a maintenance headache.

If the user wants feedback between every field entry (or every few entries, or every few seconds), you could use an AJAX call to ask the server for validation without a full page refresh.

This will, of course result in more requests than doing the validation entirely on the client, and if many of your users have bad network connections there could be latency in giving them the feedback. My guess is the total bandwidth usage is about the same. You use some for every validation round-trip, but those are small. It may be outweighed by all that validation JS that you're not going to send to clients.

The main benefit is the maintenance and FUD that you'd otherwise have keeping the client and server validation in sync. There's also the time savings in never having to write the validation javascript.

In any case, it may be worth taking a step back and asking what your requirements are.

solublefish
  • 1,681
  • 2
  • 18
  • 24
  • My JS is cached since it is in a separate file so (unfortunately) the total bandwidth will not be the same in either case. But I still think that going the way you (and @DennisRongo) suggest will make things easier for me in future. – Ramanpreet Singh Jan 28 '13 at 07:35
  • Other things I tried: - The "expression" way as suggested by @StefanSieber - turned out very complex for the formulae I am using. – Ramanpreet Singh Jan 28 '13 at 07:39
  • - Reverse Polish Calculator as suggested by @JordanDavidson - again a bit too complex for my formulae – Ramanpreet Singh Jan 28 '13 at 07:40
0

The Microsoft.CSharp.CSharpCodeProvider provider can compile code on-the-fly. In particular, see CompileAssemblyFromFile.

This would allow you to execute code at runtime from a web.config for instance; however use with caution.

webbexpert
  • 704
  • 9
  • 15
0

You could write C# classes to model your expressions with classes such as Expression, Value, BooleanExpr, etc. (an Abstract Syntax Tree)

e.g.

Expression resultExpression = new ValueOf("T1").Times(new ValueOf("T2")).GreaterThan(600).IfElse("RED","GREEN")
                                    ^Variable              ^Variable        ^Value=>BoolExpr   ^(Value, Value) => Value

These expressions could then be used to evaluation in C# AND to emit Java script for the checks:

String result = resultExpression.bind("T1", 10).bind("T2",20).evaluate() //returns "RED"
String jsExpression resultExpression.toJavaScript // emits T1 * T2 > 600 ? "RED" : "GREEN"
Stefan Sieber
  • 483
  • 4
  • 7
  • This *could* serve as a decent enough solution though I would have to then replace the emitted JS with the names of my textboxes on UI. I will give it a shot and let you know. – Ramanpreet Singh Jan 24 '13 at 06:04
  • If you need to do some mapping for the textboxes, you could use a solution similar to the bind() when evaluating. --> resultExpression.toJavascript.bind("T1","nameOfT1").bind("T2","nameOfT2).Code – Stefan Sieber Jan 24 '13 at 07:09
0

You can make a low level calculator class that uses strings as input and pushes and pops things onto a stack. Look up a "Reverse Polish Calculator". If the number of inputs you are using doesn't change this would be a pretty slick way to store your equations. You would be able to store them in a text file or in a config file very easily.

for instance:

string Equation = "V1,V2,+";

string ParseThis = Equation.Replace("V1", "34").Replace("V2", "45");

foreach(string s in ParseThis.split(',')) {
   if (s == "+") {
     val1 = stack.Pop();
     val2 = stack.Pop();
     return int.parse(val1) + int.Parse(val2);
   }
   else {
     stack.Push(s);
   }
}

obviously this gets more complicated with different equations but it could allow you to store your equations as strings anywhere you want.

apologies if any of the syntax is incorrect but this should get you going in the right direction.

Jordan Davidson
  • 419
  • 4
  • 14
0

The simplest solution would be to implement the formulae once in C# server-side, and use AJAX to evaluate the expressions from the client when changes are made. This might slow down the page.

If you want the formulae evaluated client-side and server-side but written only once, then I think you will need to do something like:

  • Pull the formulae out into a separate class
  • For the client-side:
  • For the server-side:
    • Call into the formulae class, passing in the values from the form data (or controls if this is web-forms)
    • Take the necessary actions using the results of the formulae

.. or you could do the converse, and write the formulae in Javascript, and use a C# Javascript engine to evaluate that code server-side.

I wouldn't spend time writing a custom expression language, or writing code to translate C# to Javascript, as suggested by some of the other answers. As shown in the questions I linked to, these already exist. This is a distraction from your business problem. I would find an existing solution which fits and benefit from someone else's work.

Community
  • 1
  • 1
Rich
  • 15,048
  • 2
  • 66
  • 119