Chapter 8. Designing behavior-centric programs

 

This chapter covers

  • Representing behaviors as functions
  • Extending program behavior
  • Working with functions and closures
  • Testing clients using decision trees

In chapter 7, we discussed data-centric applications, and you learned that the first step to designing functional programs is to define the relevant data structures. There are also cases where the data structure contains some form of behavior. One case might be a command that the user can invoke or tasks that the program executes at some point. Instead of hard-coding every behavioral feature, we want to work with them uniformly, so we need to keep them in a data structure that can be easily modified, either before the compilation or at runtime.

An example of a behavior-centric application that we discussed in chapter 7 is one that processes images using graphical filters. The application needs to store the filters and add or remove them depending on what filters you want to apply. When representing this in the program, we could use a list for the actual collection of filters to apply; the harder question is what data structure we should use to represent the filters themselves. Clearly, a filter isn’t really data, although it may be parameterized in some fashion. Instead, it denotes behavior, and the simplest way for representing behavior in a functional language is to use a function.

8.1. Using collections of behaviors

8.1.1. Representing behaviors as objects

8.1.2. Representing behaviors as functions in C#

8.1.3. Using collections of functions in C#

8.1.4. Using lists of functions in F#

8.2. Idioms for working with functions

8.2.1. The strategy design pattern

8.2.2. The command design pattern

8.2.3. Capturing state using closures in F#

8.3. Working with composed behaviors

8.3.1. Records of functions

8.3.2. Building composed behaviors

8.3.3. Further evolution of F# code

8.4. Combining data and behaviors

8.4.1. Decision trees

8.4.2. Decision trees in F#

8.4.3. Decision trees in C#

8.5. Summary