150
Applying functional programming approaches in object oriented languages Mark Needham © ThoughtWorks 2010

Mixing functional programming approaches in an object oriented language

Embed Size (px)

DESCRIPTION

My slides from Biz Tech Delhi

Citation preview

Page 1: Mixing functional programming approaches in an object oriented language

Applying functional programming approaches in object oriented languages

Mark Needham

© ThoughtWorks 2010

Page 2: Mixing functional programming approaches in an object oriented language

C# 1.0

Page 3: Mixing functional programming approaches in an object oriented language

int[] ints = new int[] {1, 2, 3, 4, 5}

 

Page 4: Mixing functional programming approaches in an object oriented language

int[] Filter(int[] ints){    ArrayList results = new ArrayList();

    foreach (int i in ints)    {

if (i % 2 == 0) {

results.Add(i); }

    }

    return results.ToArray(typeof(int));}

Page 5: Mixing functional programming approaches in an object oriented language

int[] ints = new int[] {1, 2, 3, 4, 5}

 

Page 6: Mixing functional programming approaches in an object oriented language

int[] Filter(int[] ints){    ArrayList results = new ArrayList();

    foreach (int i in ints)    {

if (i > 3 == 0){

results.Add(i);}

    }

    return results.ToArray(typeof(int));}

Page 7: Mixing functional programming approaches in an object oriented language

int[] Filter(int[] ints){    ArrayList results = new ArrayList();

    foreach (int i in ints)    {

if (i % 2 == 0){

results.Add(i);}

    }

    return results.ToArray(typeof(int));}

Page 8: Mixing functional programming approaches in an object oriented language

int[] Filter(int[] ints){    ArrayList results = new ArrayList();

    foreach (int i in ints)    {

if (i >3 == 0){

results.Add(i);}

    }

    return results.ToArray(typeof(int));}

Page 9: Mixing functional programming approaches in an object oriented language

interface IIntegerPredicate{

bool Matches(int value);}

Page 10: Mixing functional programming approaches in an object oriented language

class EvenPredicate : IIntegerPredicate{

bool Matches(int value){

return value % 2 == 0;}

}

Page 11: Mixing functional programming approaches in an object oriented language

class GreaterThan3Predicate : IIntegerPredicate{

bool Matches(int value){

return value > 3;}

}

Page 12: Mixing functional programming approaches in an object oriented language

int[] Filter(int[] ints, IIntegerPredicate predicate){    ArrayList results = new ArrayList();

    foreach (int i in ints)    {

if (predicate.Matches(i)){

results.Add(i);}

    }

    return results.ToArray(typeof(int));}

Page 13: Mixing functional programming approaches in an object oriented language

int[] ints = new int[] {1, 2, 3, 4, 5 };

int[] even = Filter(ints, new EvenPredicate());

int[] greaterThan3 = Filter(ints, new GreaterThan3Predicate());

Page 14: Mixing functional programming approaches in an object oriented language

interface IIntegerPredicate{

bool Matches(int value);}

Page 15: Mixing functional programming approaches in an object oriented language

bool delegate IntegerPredicate(int value);

Page 16: Mixing functional programming approaches in an object oriented language

bool Even(int value){

return value % 2 == 0;}

Page 17: Mixing functional programming approaches in an object oriented language

bool GreaterThan3(int value){

return value > 3;}

Page 18: Mixing functional programming approaches in an object oriented language

int[] Filter(int[] ints, IntegerPredicate predicate){    ArrayList results = new ArrayList();

    foreach (int i in ints)    {                

if (predicate(i)) {

results.Add(i); }

    }

    return results.ToArray(typeof(int));}

Page 19: Mixing functional programming approaches in an object oriented language

int[] ints = new int[] {1, 2, 3, 4, 5 };

int[] even = Filter(ints, new IntegerPredicate(Even));

int[] greaterThan3 = Filter(ints,  new

IntegerPredicate(GreaterThan3));

Page 20: Mixing functional programming approaches in an object oriented language

C# 2.0

 

Page 21: Mixing functional programming approaches in an object oriented language

Inference

int[] ints = new int[] {1, 2, 3, 4, 5 };

int[] even = Filter(ints, new IntegerPredicate(Even));

int[] greaterThan3 = Filter(ints, new IntegerPredicate(GreaterThan3));

Page 22: Mixing functional programming approaches in an object oriented language

Inference

int[] ints = new int[] {1, 2, 3, 4, 5 };

int[] even = Filter(ints, Even);

int[] greaterThan3 = Filter(ints, GreaterThan3);

Page 23: Mixing functional programming approaches in an object oriented language

Generics

delegate bool IntegerPredicate(int value);

Page 24: Mixing functional programming approaches in an object oriented language

Generics

delegate bool Predicate<T> (T value);

Page 25: Mixing functional programming approaches in an object oriented language

Generics

int[] Filter(int[] ints, IntegerPredicate predicate){

ArrayList results = new ArrayList();

foreach (int i in ints){

if (predicate(i)){

results.Add(i);}

}

return results.ToArray(typeof(int));}

Page 26: Mixing functional programming approaches in an object oriented language

Generics

T[] Filter<T>(T[] values, Predicate<T> predicate){

List<T> results = new List<T>();

foreach (T i in value){

if (predicate(i)){

results.Add(i);}

}

return results.ToArray();}

Page 27: Mixing functional programming approaches in an object oriented language

Iterators

IEnumerable<T> Filter<T>(IEnumerable<T> values, Predicate<T> p)

{List<T> results = new List<T>();

foreach (T i in value){

if (p(i)){

results.Add(i);}

}

return results;}

Page 28: Mixing functional programming approaches in an object oriented language

Iterators

IEnumerable<T> Filter<T>(IEnumerable<T> values, Predicate<T> p)

{foreach (T i in value){

if (p(i)){

yield return i;}

}}

Page 29: Mixing functional programming approaches in an object oriented language

Anonymous Methods

IEnumerable<int> greaterThan3 = Filter(ints, GreaterThan3);

Page 30: Mixing functional programming approaches in an object oriented language

Anonymous Methods

IEnumerable<int> greaterThan3 = Filter(ints, delegate(int value) { return value > 3; });

Page 31: Mixing functional programming approaches in an object oriented language

Anonymous Methods

int minimumValue = 3;

IEnumerable<int> greaterThan3 = Filter(ints, delegate(int value) { return value > minimumValue; });

Page 32: Mixing functional programming approaches in an object oriented language

C# 3.0

 

Page 33: Mixing functional programming approaches in an object oriented language

Lambdas

int minimumValue = 3;

IEnumerable<int> greaterThan3 = Filter(ints, delegate(int value) { return value > minimumValue; });

Page 34: Mixing functional programming approaches in an object oriented language

Lambdas

int minimumValue = 3;

IEnumerable<int> greaterThan3 = Filter(ints, value => value > minimumValue);

Page 35: Mixing functional programming approaches in an object oriented language

More Type Inference

int minimumValue = 3;

IEnumerable<int> greaterThan3 = Filter(ints, value => value > minimumValue);

Page 36: Mixing functional programming approaches in an object oriented language

More Type Inference

int minimumValue = 3;

var greaterThan3 = Filter(ints, value => value > minimumValue);

Page 37: Mixing functional programming approaches in an object oriented language

Extension Methods

int minimumValue = 3;

var greaterThan3 = Filter(ints, value => value > minimumValue);

Page 38: Mixing functional programming approaches in an object oriented language

Extension Methods

int minimumValue = 3;

var greaterThan3 = ints.Filter(value => value > minimumValue);

Page 39: Mixing functional programming approaches in an object oriented language

LINQ

Page 40: Mixing functional programming approaches in an object oriented language

LINQ

New delegates in System namespaceAction<T>, Action<T1, T2>, Func<TResult>, Func<T1, TResult> etc.

Page 41: Mixing functional programming approaches in an object oriented language

LINQ

New delegates in System namespaceAction<T>, Action<T1, T2>, Func<TResult>, Func<T1, TResult> etc.

System.LinqExtension methods Where, Select, OrderBy etc.

Page 42: Mixing functional programming approaches in an object oriented language

LINQ

New delegates in System namespaceAction<T>, Action<T1, T2>, Func<TResult>, Func<T1, TResult> etc.

System.LinqExtension methods Where, Select, OrderBy etc. Some compiler magic to translate sql style code to method calls

Page 43: Mixing functional programming approaches in an object oriented language

LINQ

var even = ints.Where(value => value % 2 == 0) var greaterThan3 = ints.Where(value => value > 3) or

var even = from value in ints                  where value % 2 == 0                  select value  var greaterThan3 = from value in ints                                       where value > 3                                                   select value                                      

Page 44: Mixing functional programming approaches in an object oriented language

Interfaces

Delegates

Anonymous methods

Lambdas

Page 45: Mixing functional programming approaches in an object oriented language

So this functional programming thing…

Page 46: Mixing functional programming approaches in an object oriented language

http://www.flickr.com/photos/stuartpilbrow/2938100285/sizes/l/

Page 47: Mixing functional programming approaches in an object oriented language

Higher order functions

Page 48: Mixing functional programming approaches in an object oriented language

var ints = new int[] {1, 2, 3, 4, 5 };

var greaterThan3 = ints.Where(value => value > 3)

var even = ints.Where(value => value % 2 == 0)

Page 49: Mixing functional programming approaches in an object oriented language

Pure functions

Page 50: Mixing functional programming approaches in an object oriented language

Immutability

Page 51: Mixing functional programming approaches in an object oriented language

Lazy evaluation

Page 52: Mixing functional programming approaches in an object oriented language

Iterators

IEnumerable<T> Filter<T>(IEnumerable<T> values, Predicate<T> p)

{foreach (T i in value){

if (p(i)){

yield return i;}

}}

Page 53: Mixing functional programming approaches in an object oriented language

Recursion & Pattern Matching

Page 54: Mixing functional programming approaches in an object oriented language

Transformational Mindset

We can just pass functions around instead in most cases- find an example where it still makes sense to use the GOF approach though.

Page 55: Mixing functional programming approaches in an object oriented language

Input -> ??? -> ??? -> ??? -> Output

Page 56: Mixing functional programming approaches in an object oriented language

http://www.emt-india.net/process/petrochemical/img/pp4.jpg

Page 57: Mixing functional programming approaches in an object oriented language

So why should you care?

Page 58: Mixing functional programming approaches in an object oriented language

Functional can fill in the gaps in OO code

 

Page 59: Mixing functional programming approaches in an object oriented language

Programming in the…

LargeMedium

Small

Page 60: Mixing functional programming approaches in an object oriented language

Programming in the …

LargeMedium

Small

“a high level that affects as well as crosscuts multiple classes and functions”

Page 61: Mixing functional programming approaches in an object oriented language

Programming in the …

LargeMedium

Small

“a single API or group of related APIs in such things as classes, interfaces, modules”

Page 62: Mixing functional programming approaches in an object oriented language

Programming in the …

LargeMedium

Small

“individual function/method bodies”

Page 63: Mixing functional programming approaches in an object oriented language

LargeMedium

Small

Page 64: Mixing functional programming approaches in an object oriented language

LargeMedium

Small

Page 65: Mixing functional programming approaches in an object oriented language

Abstractions over common operations means less code and less chances to make mistakes

Page 66: Mixing functional programming approaches in an object oriented language

Projection

Page 67: Mixing functional programming approaches in an object oriented language

 

  

 people.Select(person => person.Name)  

Page 68: Mixing functional programming approaches in an object oriented language

 

  

people.SelectMany(person => person.Pets)

Page 69: Mixing functional programming approaches in an object oriented language

Restriction

 

Page 70: Mixing functional programming approaches in an object oriented language

 

         

            people.Where(person => person.HasPets) 

Page 71: Mixing functional programming approaches in an object oriented language

Partitioning

 

Page 72: Mixing functional programming approaches in an object oriented language

 

  

people.Take(5)

Page 73: Mixing functional programming approaches in an object oriented language

 

  

people.Skip(5)

Page 74: Mixing functional programming approaches in an object oriented language

 

  

            people.TakeWhile(person =>                             person.Name != "David")

Page 75: Mixing functional programming approaches in an object oriented language

 

              people.SkipWhile(person =>                                 person.Name != "David")

Page 76: Mixing functional programming approaches in an object oriented language

Set

 

Page 77: Mixing functional programming approaches in an object oriented language

 

people.Select(person => person.Name).Distinct()

Page 78: Mixing functional programming approaches in an object oriented language

 

 people.Union(someOtherPeople) 

Page 79: Mixing functional programming approaches in an object oriented language

 

  

people.Intersect(someOtherPeople)

Page 80: Mixing functional programming approaches in an object oriented language

 

  

people.Except(someOtherPeople)

Page 81: Mixing functional programming approaches in an object oriented language

Ordering and Grouping

 

Page 82: Mixing functional programming approaches in an object oriented language

 

  

people.OrderBy(person => person.Name)  

Page 83: Mixing functional programming approaches in an object oriented language

 

  

people.GroupBy(person => person.Name)

Page 84: Mixing functional programming approaches in an object oriented language

Aggregation

 

Page 85: Mixing functional programming approaches in an object oriented language

 

  

people.Count()

Page 86: Mixing functional programming approaches in an object oriented language

 

  

people.Select(person => person.Age).Sum()

Page 87: Mixing functional programming approaches in an object oriented language

 

  

people.Select(person => person.Age).Min()

Page 88: Mixing functional programming approaches in an object oriented language

 

  

people.Select(person => person.Age).Max()

Page 89: Mixing functional programming approaches in an object oriented language

 

  

people.Select(person => person.Age).Average()

Page 90: Mixing functional programming approaches in an object oriented language

 

  

       people.Select(person => person.Age)            .Aggregate(0, (totalAge, nextAge) =>                     nextAge % 2 == 0                         ? nextAge + totalAge                         : totalAge)

Page 91: Mixing functional programming approaches in an object oriented language

Joining

 

Page 92: Mixing functional programming approaches in an object oriented language

 

          people.Join(addresses,                           person => person.PersonId,                  address => address.PersonId,                     (person, address) => new {                                         person, address})

Page 93: Mixing functional programming approaches in an object oriented language

Embrace the collection

 

Page 94: Mixing functional programming approaches in an object oriented language

 var first = “Mark”;var middle = “Harold”;var surname = “Needham”;

var fullname = first + “ “ + middle + “ “ + surname;

or

var names = new[] {first, middle, surname};var fullname = String.Join(“ “, names);

Page 95: Mixing functional programming approaches in an object oriented language

 public class SomeObject{ public SomeObject(string p1, string p2, string p3) { if(p1 == null) throw new Exception(…); if(p2 == null) throw new Exception(…); if(p3 == null) throw new Exception(…);

// rest of constructor logic }}

Page 96: Mixing functional programming approaches in an object oriented language

 public class SomeObject{ public SomeObject(string p1, string p2, string p3) { var parameters = new[] {p1, p2, p3}; if(parameters.Any(p => p = null) throw new Exception(…).

// rest of constructor logic }}

Page 97: Mixing functional programming approaches in an object oriented language

LargeMedium

Small

Page 98: Mixing functional programming approaches in an object oriented language

We can just pass functions around instead in most cases- find an example where it still makes sense to use the GOF approach though.

Page 99: Mixing functional programming approaches in an object oriented language
Page 100: Mixing functional programming approaches in an object oriented language

 

 

public class SomeObject{

private readonly IStrategy strategy;

public SomeObject(IStrategy strategy){

this.strategy = strategy;}

public void DoSomething(string value){

strategy.DoSomething(value);}

}

Page 101: Mixing functional programming approaches in an object oriented language

 

 public class Strategy : IStrategy{

public void DoSomething(string value){

// do something with string}

}

Page 102: Mixing functional programming approaches in an object oriented language

 

 

public class SomeObject{

private readonly Action<string> strategy;

public SomeObject(Action<string> strategy){

this.strategy = strategy;}

public void DoSomething(string value){

strategy(value);}

}

Page 103: Mixing functional programming approaches in an object oriented language

 

Hole in the middle pattern

Page 104: Mixing functional programming approaches in an object oriented language

 

 

public class ServiceCache<Service>{ protected Res FromCacheOrService <Req, Res>(Func<Res> serviceCall, Req request) { var cachedRes = cache.RetrieveIfExists( typeof(Service), typeof(Res), request);

  if(cachedRes == null) { cachedRes = serviceCall(); cache.Add(typeof(Service), request, cachedRes); }

return (Res) cachedRes; }}

Page 105: Mixing functional programming approaches in an object oriented language

 

 public class CachedService : ServiceCache<IService>{

public MyResult GetMyResult(MyRequest request){

          return FromCacheOrService(()                  => service.GetMyResult(request), request);

}}

Page 106: Mixing functional programming approaches in an object oriented language

 

Maybe?

Page 107: Mixing functional programming approaches in an object oriented language

 

public interface Maybe<T>{

bool HasValue();T Value();

}

Page 108: Mixing functional programming approaches in an object oriented language

 

public class Some<T> : Maybe<T>{

private readonly T theThing;

public Some(T theThing){

this.theThing = theThing;}

public bool HasValue (){

return true;}

public T Value(){

return theThing;}

}

Page 109: Mixing functional programming approaches in an object oriented language

 public class None<T> : Maybe<T>{

public bool HasValue (){

return false;}

public T Value(){

throw new NotImplementedException();}

}

Page 110: Mixing functional programming approaches in an object oriented language

  public class Some{

public static Some<T> Thing<T>(T thing) : where T : class

{return new Some<T>(thing);

}}

Page 111: Mixing functional programming approaches in an object oriented language

 

public class No{

public static None<T> Thing<T>()

{return new None<T>();

}}

Page 112: Mixing functional programming approaches in an object oriented language

 

public static class MaybeExtensions{

public static Maybe<T> Maybify<T>(this T source)where T : class

{if(source == null)

return No.Thing<T>();

return Some.Thing(source);}

}

recordFromDatabase.Maybify():

Page 113: Mixing functional programming approaches in an object oriented language

 

public class FooService{

public Foo FindOrCreate(int fooId){

var foo = fooRepository.Find(fooId);

if(foo.HasValue()){

return foo.Value();}

return fooRepository.Create(fooId);}

}

Page 114: Mixing functional programming approaches in an object oriented language

 

Continuation Passing Style

Page 115: Mixing functional programming approaches in an object oriented language

 

static void Identity<T>(T value, Action<T> k) {

k(value); }

Page 116: Mixing functional programming approaches in an object oriented language

 

Identity("foo", s => Console.WriteLine(s));

Page 117: Mixing functional programming approaches in an object oriented language

 

Identity("foo", s => Console.WriteLine(s));

as compared to

var foo = Identity(“foo”);Console.WriteLine(foo);

Page 118: Mixing functional programming approaches in an object oriented language

 

public ActionResult Submit(string id, FormCollection form) {    var shoppingBasket = CreateShoppingBasketFrom(id, form);      return IsValid(shoppingBasket, ModelState,          () => RedirectToAction("index", "ShoppingBasket", new { shoppingBasket.Id} ),  

() => LoginUser(shoppingBasket,                  () =>                  {                    ModelState.AddModelError("Password", "User name/email address was incorrect - please re-enter");                      return RedirectToAction("index", ""ShoppingBasket",

new { Id = new Guid(id) });                 }, user =>                  {                    shoppingBasket.User = user;                      UpdateShoppingBasket(shoppingBasket);                      return RedirectToAction("index", "Purchase",   

new { Id = shoppingBasket.Id }); }         )); }

Page 119: Mixing functional programming approaches in an object oriented language

 

private RedirectToRouteResult IsValid(ShoppingBasket shoppingBasket,                                       ModelStateDictionary modelState,                                        Func<RedirectToRouteResult> failureFn,                     

Func<RedirectToRouteResult> successFn) {   return validator.IsValid(shoppingBasket, modelState) ? successFn() : failureFn(); }  

private RedirectToRouteResult LoginUser(ShoppingBasket shoppingBasket,                                                                  Func<RedirectToRouteResult> failureFn,                                                                Func<User,RedirectToRouteResult> successFn) {

User user = null; try {

user = userService.CreateAccountOrLogIn(shoppingBasket); }   catch (NoAccountException) {

return failureFn(); }   return successFn(user);

}

Page 120: Mixing functional programming approaches in an object oriented language

 

Passing functions around

Page 121: Mixing functional programming approaches in an object oriented language

 

private void AddErrorIf<T>(Expression<Func<T>> fn, ModelStateDictionary modelState,

Func<ModelStateDictionary, Func<T,string, string, bool>> checkFn)

{var fieldName = ((MemberExpression)fn.Body).Member.Name;var value = fn.Compile().Invoke();var validationMessage = validationMessages[fieldName]);

checkFn.Invoke(modelState)(value, fieldName, validationMessage);}

AddErrorIf(() => person.HasPets, modelState, m => (v, f, e) => m.AddErrorIfNotEqualTo(v,true, f, e));

AddErrorIf(() => person.HasChildren, modelState, m => (v, f, e) => m.AddErrorIfNull(v, f, e));

Page 122: Mixing functional programming approaches in an object oriented language

 

http://www.thegeekshowpodcast.com/home/mastashake/thegeekshowpodcast.com/wp-content/uploads/2009/07/wtf-cat.jpg

Page 123: Mixing functional programming approaches in an object oriented language

So what could possibly go wrong?

 

http://icanhascheezburger.files.wordpress.com/2009/06/funny-pictures-cat-does-not-think-plan-will-fail.jpg

Page 124: Mixing functional programming approaches in an object oriented language

Hard to diagnose errors

 

Page 125: Mixing functional programming approaches in an object oriented language

var people = new [] {

new Person { Id=1, Address = new Address { Road = "Ewloe Road" }},

new Person { Id=2},new Person { Id=3, Address =

new Address { Road = "London Road"}} };

people.Select(p => p.Address.Road); 

Page 126: Mixing functional programming approaches in an object oriented language

Null Reference Exception on line 23

Page 127: Mixing functional programming approaches in an object oriented language

http://www.flickr.com/photos/29599641@N04/3147972713/

Page 128: Mixing functional programming approaches in an object oriented language

public T Tap(T t, Action action) {    action();    return t;}

Page 129: Mixing functional programming approaches in an object oriented language

people    .Select(p => Tap(p, logger.debug(p.Id))    .Select(p => p.Address.Road); 

Page 130: Mixing functional programming approaches in an object oriented language

if we have side effects  then favour foreach construct

foreach(var item in items){        itemRepository.Save(item);}

Page 131: Mixing functional programming approaches in an object oriented language

rather than:

items.ToList().ForEach(item => itemRepository.Save(item));

Page 132: Mixing functional programming approaches in an object oriented language

Readability

 

Page 133: Mixing functional programming approaches in an object oriented language

Lazy evaluation can have unexpected consequences

 

Page 134: Mixing functional programming approaches in an object oriented language

 

        IEnumerable<string> ReadNamesFromFile()        {            using(var fileStream = new FileStream("names.txt",                                                         FileMode.Open))            using(var reader = new StreamReader(fileStream))            {                var nextLine = reader.ReadLine();                while(nextLine != null)                {                    yield return nextLine;                    nextLine = reader.ReadLine();                }            }        }

Page 135: Mixing functional programming approaches in an object oriented language

 

        IEnumerable<Person> GetPeople()        {            return ReadNamesFromFile()

.Select(name => new Person(name));        }

Page 136: Mixing functional programming approaches in an object oriented language

 

     IEnumerable<Person> people = GetPeople();         foreach (var person in people)     {         Console.WriteLine(person.Name);     }         Console.WriteLine("Total number of people: " +

people.Count());

Page 137: Mixing functional programming approaches in an object oriented language

Encapsulation is still important

 

Page 138: Mixing functional programming approaches in an object oriented language

public Money CalculateSomething(Func<Customer, DateTime, Money> calculation)

{// do some calculation

}

Page 139: Mixing functional programming approaches in an object oriented language

public delegate Money PremiumCalculation(Customer customer, DateTime renewalDate);

Page 140: Mixing functional programming approaches in an object oriented language

public Money CalculateSomething(PremiumCalculation calculation)

{// do some calculation

}

Page 141: Mixing functional programming approaches in an object oriented language

 

Total salary for a company company.Employees

.Select(employee => employee.Salary) .Sum()

This could lead to duplication

What if we add rules to the calculation?

Who should really have this responsibility?.Sum()

Page 142: Mixing functional programming approaches in an object oriented language

Linq isn't the problem here, it's where we have put it

 

Page 143: Mixing functional programming approaches in an object oriented language

Company naturally has the responsibility so encapsulate the logic here

Page 144: Mixing functional programming approaches in an object oriented language

class Company{    public int TotalSalary    {        get         {            return employees.Select(e =>e.Salary).Sum();         }     } }

Page 145: Mixing functional programming approaches in an object oriented language

Sometimes we need to go further

 

Page 146: Mixing functional programming approaches in an object oriented language

If both Company and Division have employees do we duplicate the logic for total salary?

Page 147: Mixing functional programming approaches in an object oriented language

IEnumerable<T> and List<T> make collections easy but sometimes it is still better to create a

class to represent a collection

Page 148: Mixing functional programming approaches in an object oriented language

 

class EmployeeCollection{    private List<Employee> employees;       public int TotalSalary    {        get        {            return employees.Select(e => e.Salary).Sum();         }    }}

Page 149: Mixing functional programming approaches in an object oriented language

In conclusion…

 

Page 150: Mixing functional programming approaches in an object oriented language

Mark [email protected]

© ThoughtWorks 2010