Create mobile apps with HTML5, JavaScript and Visual Studio

(Elle) #1

msdnmagazine.com February 2014 25


that even understands units of measure, and you’ve got a powerful


tool for performing calculations on large sets of data.


Th ere’s much more to F# and other functional languages that’s


still far beyond my reach. But what I want to do in this column


is focus on a way to quickly benefit from one particular aspect


of functional languages without making a huge investment:


moving logic from the database into my application. Th is is the way


I like to learn: fi nd a few things I can understand and use them to


take some baby steps into a new platform, language, framework


or other type of tool.


I’ve heard Reese try to make it clear to developers that using


F# doesn’t mean switching development languages. In the same


way you might use a LINQ query or a stored procedure to solve a


particular problem, you can create a library of F# methods to solve


the kinds of problems in your app that functional languages are


really good at.


What I’ll focus on here is extracting business logic that was built into


my database, logic for handling large sets of data—something at which


the database is excellent—and replacing it with functional methods.


And because F# is designed to work with sets and is really clever


with mathematical functions, the code can be more effi cient than


it might be in SQL or in procedural languages such as C# or Visual


Basic. It’s so easy to have F# execute the logic on the items in the


set in parallel. Not only can this reduce the amount of code you’d


likely need in a procedural language to emulate this behavior, the


parallelization means the code will run much faster. You could


design your C# code to run in parallel, but I’d rather not go through


that eff ort, either.


A Real-World Problem


Many years ago, I wrote a Visual Basic 5 app that had to collect,


maintain, and report a lot of scientifi c data and perform a lot of


calculations. Some of those calculations were so complex I sent


them to an Excel API.


One of the calculations involved determining the pounds per


square inch (PSI) based on the amount of weight that caused


a chunk of material to break. Th e chunk could be any one of a


number of cylindrical shapes and sizes. The app would use the


measurements of the cylinder and, depending on its shape and


size, a specifi c formula to calculate its area. It would then apply a


relevant tolerance factor and, fi nally, the amount of weight it took


to break the cylinder. All of this together provided the PSI for the


particular material being tested.


In 1997, leveraging the Excel API to evaluate the formula from within


Visual Basic 5 and Visual Basic 6 felt like a pretty clever solution.


Moving the Eval


Years later, I revamped the application in .NET. At that time, I


decided to take advantage of the power of SQL Server to execute


the PSI calculation on large sets of cylinders aft er they were updated


by a user, rather than having the user’s computer spend time on all


of those calculations. Th at worked out pretty well.


More years passed and my ideas about business logic in the


database changed. I wanted to pull that calculation back to the


client side and, of course, the client machines were faster by then,


anyway. It wasn’t too diffi cult to rewrite the logic in C#. Aft er a user


updated a series of cylinders with the weight it took to break them


(the load, represented in pounds), the app would iterate through


the updated cylinders and calculate the PSI. Th en I could update


cylinders in the database with their new loads and PSI values.


For the sake of comparing familiar C# to the fi nal outcome in F#


(which you’ll see shortly), I’ve provided the listing of the cylinder


type, CylinderMeasurements, in Figure 1 and my C# Calculator


class in Figure 2, so you can see how I derive the PSIs for a set of


public static class CylinderCalculator
{
private static CylinderMeasurement _currentCyl;

public static void UpdateCylinders(IEnumerable<CylinderMeasurement> cyls) {
foreach (var cyl in cyls)
{
_currentCyl = cyl;
cyl.Psi = GetPsi();
}
}

private static double GetPsi() {
var area = GetAreaForCylinder();
return PsiCalculator(area);
}

private static double GetAreaForCylinder() {
switch (_currentCyl.CylinderType)
{
case CylinderType.FourFourEightCylinder:
return 3.14159*((_currentCyl.WidthA + _currentCyl.WidthB)/2)/2*
((_currentCyl.WidthA + _currentCyl.WidthB)/2/2);
case CylinderType.SixSixTwelveCylinder:
return 3.14159*((_currentCyl.WidthA + _currentCyl.WidthB)/2)/2*
((_currentCyl.WidthA + _currentCyl.WidthB)/2/2);
case CylinderType.ThreeThreeSixCylinder:
return _currentCyl.WidthA*_currentCyl.WidthB;
case CylinderType.TwoTwoTwoCylinder:
return ((_currentCyl.WidthA + _currentCyl.WidthB)/2)*
((_currentCyl.WidthA + _currentCyl.WidthB)/2);
default:
throw new ArgumentOutOfRangeException();
}
}

private static int PsiCalculator(double area) {
if (_currentCyl.LoadPounds > 0 && area > 0)
{
return (int) (Math.Round(_currentCyl.LoadPounds/area/1000*
_currentCyl.ToleranceFactor, 2)*1000);
}
return 0;
}
}

Figure 2 Calculator Class to Calculate PSI


You can create a library of


F# methods to solve the kinds


of problems in your app that


functional languages are


really good at.

Free download pdf