官术网_书友最值得收藏!

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.

主站蜘蛛池模板: 广宁县| 东兴市| 铜鼓县| 泽州县| 唐海县| 开江县| 洪湖市| 黎城县| 松潘县| 闽侯县| 延寿县| 马尔康县| 古田县| 乌苏市| 乐平市| 龙泉市| 平昌县| 瓮安县| 昭通市| 盐边县| 日喀则市| 海伦市| 长寿区| 太白县| 郯城县| 惠州市| 松潘县| 襄樊市| 凤城市| 林口县| 丰原市| 祥云县| 上思县| 兴隆县| 昌吉市| 四平市| 呼图壁县| 尼玛县| 南澳县| 陆良县| 鄂托克前旗|