Functional programming
Functional programming is a programming paradigm that relies on the functional transformation of data between stages, not so different from the dataflow programming we just saw. The main addendum to the data flow paradigm is that, within the functional one, there is a specific functional transformation, while in the data flow paradigm such transformations occur in a specific idiom-based way that can be functional-based, script-based (imperative paradigm), component-based, or anything else.
In functional programming, data is always immutable and functions are responsible for data transformation. Anything in functional style is a data transformation. Although a decisional statement (if
) cannot exist, a functional transformation from data containing predicate to data containing the Boolean result may occur:
//procedural style var sourceData = new { TotalAmount = 12345.67, PaidAmount = 12345.67 }; if (sourceData.PaidAmount == sourceData.TotalAmount) { //do something } //functional style //a simple enumerable new[] { new { TotalAmount = 12345.67, PaidAmount = 12345.67 } } //transformation block .Select(x => new { x.TotalAmount, x.PaidAmount, CanContinue = x.TotalAmount == x.PaidAmount, }) //if .Where(x => x.CanContinue) //do something .ToArray();
A widely known design pattern is the data mapper one. This design tries to decouple and translate objects of a layer (for historic purposes, the domain layer) into another one (for historic purposes, the data model one).
Here is a simple procedural (imperative with subroutines) programming style example in C#:
class Program { static void Main(string[] args) { //retrieve invoices from DB var invoicesFromDB = GetInvoicesFromDB(); //map those invoices to business model objects var invoicesForBusiness = ConvertInvoicesForBusiness(invoicesFromDB); } /// <summary> /// Reads invoices from a (fake) database /// </summary> /// <returns></returns> static InvoiceFromDB[] GetInvoicesFromDB() { var result = new InvoiceFromDB[3]; result[0] = new InvoiceFromDB { CustomerName = "Mr. Black", Number = "100/2015/BBC", BaseAmount = 24560, VATMultiplier = 1.22, }; result[1] = new InvoiceFromDB { CustomerName = "White Co Ltd", Number = "240/2015/BBC", BaseAmount = 422480, VATMultiplier = 1.22, }; result[2] = new InvoiceFromDB { CustomerName = "Green Woods inc.", Number = "22/2015/BBC", BaseAmount = 8500, VATMultiplier = 1.22, }; return result; } /// <summary> /// Converts invoices from database to invoices for business needs /// </summary> static InvoiceBusiness[] ConvertInvoicesForBusiness(InvoiceFromDB[] source) { var result = new InvoiceBusiness[source.Length]; for (int i = 0; i < source.Length; i++) result[i] = new InvoiceBusiness { Number = source[i].Number, CustomerName = source[i].CustomerName, BaseAmount = source[i].BaseAmount, VATMultiplier = source[i].VATMultiplier, }; return result; } } public class InvoiceFromDB { public string CustomerName { get; set; } public string Number { get; set; } public double BaseAmount { get; set; } public double VATMultiplier { get; set; } } public class InvoiceBusiness { public string CustomerName { get; set; } public string Number { get; set; } public double BaseAmount { get; set; } public double VATMultiplier { get; set; } public double Total { get { return BaseAmount * VATMultiplier; } } }
In a functional style, the same program will benefit from the use of the enumerator pattern (for static data such as this one) or triggers that will notify for observed data changes.
Later, the transformation logic will take place within a function.
Here is the same preceding example in a functional style made with LINQ querying in C#:
class Program { static void Main(string[] args) { var businessInvoices = //stage 1 - read db data GetInvoicesFromDB() //stage 2 - make transfomation .Select(dbinvoice => new InvoiceBusiness { Number = dbinvoice.Number, BaseAmount = dbinvoice.BaseAmount, CustomerName = dbinvoice.CustomerName, VATMultiplier = dbinvoice.VATMultiplier, }) //force execution of the whole enumerator .ToArray(); } static IEnumerable<InvoiceFromDB> GetInvoicesFromDB() { yield return new InvoiceFromDB { CustomerName = "Mr. Black", Number = "100/2015/BBC", BaseAmount = 24560, VATMultiplier = 1.22, }; yield return new InvoiceFromDB { CustomerName = "White Co Ltd", Number = "240/2015/BBC", BaseAmount = 422480, VATMultiplier = 1.22, }; yield return new InvoiceFromDB { CustomerName = "Green Woods inc.", Number = "22/2015/BBC", BaseAmount = 8500, VATMultiplier = 1.22, }; } } public class InvoiceFromDB { public string CustomerName { get; set; } public string Number { get; set; } public double BaseAmount { get; set; } public double VATMultiplier { get; set; } } public class InvoiceBusiness { public string CustomerName { get; set; } public string Number { get; set; } public double BaseAmount { get; set; } public double VATMultiplier { get; set; } public double Total { get { return BaseAmount * VATMultiplier; } } }
What makes the preceding example different from the previous one is that the GetInvoicesFromDB
method returns an enumerable collection. Although an array is enumerable too, an array is a finite item collection. In the procedural example, all contained objects must already be in our memory before the method returns values creating a huge data state. Later, in the imperative example, such a state will be changed by the other method ConvertInvoicesForBusiness
that is responsible for creating business objects containing business stuff (Total
in the preceding example).
In the functional style example, instead of having an interactive statement that processes data in the memory, we will simply write a new function able to transform the data-oriented object into the business-oriented one. This transformation is declaratively defined with a function. The function simply states how the transformation must happen. Thus, to trigger the concrete computation and the storage (in memory) of the transformed data, we will use the .ToArray()
LINQ extension method that will evaluate the functional result and store such results into a finite item collection, the array.
Note
We will delve more deeply into functional programming and functional reactive programming in Chapter 8 , F# and Functional Reactive Programming, and Chapter 9 , Advanced FRP and Best Practices, of this book.