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

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.

主站蜘蛛池模板: 独山县| 昭苏县| 贺州市| 岑溪市| 塘沽区| 工布江达县| 定陶县| 峨眉山市| 景宁| 大同市| 平原县| 贵溪市| 万安县| 集安市| 如东县| 霍林郭勒市| 增城市| 涡阳县| 叙永县| 黄冈市| 环江| 汽车| 夏河县| 汉中市| 南郑县| 大新县| 株洲市| 丹东市| 读书| 深州市| 喜德县| 长葛市| 梅河口市| 岑巩县| 阿尔山市| 固阳县| 中江县| 藁城市| 梁山县| 台南市| 淮北市|