mixing functional and object oriented approaches to programming in c#

124
Mixing functional and object oriented approaches to programming in C# Mark Needham

Upload: mark-needham

Post on 10-May-2015

2.316 views

Category:

Technology


3 download

DESCRIPTION

A talk I did at DDD8, January 20th 2010.

TRANSCRIPT

Page 1: Mixing functional and object oriented approaches to programming in C#

Mixing functional and object oriented approaches to

programming in C#

Mark Needham

Page 2: Mixing functional and object oriented approaches to programming in C#

A bit of context

Page 3: Mixing functional and object oriented approaches to programming in C#

ThoughtWorks delivery projects

Page 4: Mixing functional and object oriented approaches to programming in C#

Web applications with somewhat complicated domains

Page 5: Mixing functional and object oriented approaches to programming in C#

5-15 developers on a team

Page 6: Mixing functional and object oriented approaches to programming in C#

Projects running for 6-12 months

Page 7: Mixing functional and object oriented approaches to programming in C#

All this means that we want to write code which is…

Page 8: Mixing functional and object oriented approaches to programming in C#

Easy to understand

Page 9: Mixing functional and object oriented approaches to programming in C#

Easy to change

Page 10: Mixing functional and object oriented approaches to programming in C#

Which leads us to what this talk is all about…

Page 11: Mixing functional and object oriented approaches to programming in C#

Organisation of code

‘The Lush Landscape of Languages’ - The ThoughtWorks Anthology

Rebecca Parsons

Page 12: Mixing functional and object oriented approaches to programming in C#

How might functional programming help us with that?

Page 13: Mixing functional and object oriented approaches to programming in C#

First class functions

Page 14: Mixing functional and object oriented approaches to programming in C#

“A programming language is said to support first class functions if functions

can be created during the execution of a program, stored in data structures,

passed as arguments to other functions, and returned as the values of other

functions”

Wikipedia

Page 15: Mixing functional and object oriented approaches to programming in C#

Immutability

Page 16: Mixing functional and object oriented approaches to programming in C#

Lazy evaluation

Page 17: Mixing functional and object oriented approaches to programming in C#

Recursion

Page 18: Mixing functional and object oriented approaches to programming in C#

Pattern matching

Page 19: Mixing functional and object oriented approaches to programming in C#

This is all very cool but…

Page 20: Mixing functional and object oriented approaches to programming in C#

Object Oriented design still has its place

Page 21: Mixing functional and object oriented approaches to programming in C#

Encapsulation

Page 22: Mixing functional and object oriented approaches to programming in C#

Abstraction

Page 23: Mixing functional and object oriented approaches to programming in C#

So how do these two paradigms work together?

Page 24: Mixing functional and object oriented approaches to programming in C#

Programming in the small/medium/large

http://weblogs.asp.net/podwysocki/archive/2009/12/14/going-hybrid-implementing-a-shopping-cart-in-f.aspx

Page 25: Mixing functional and object oriented approaches to programming in C#

In the large…

“a high level that affects as well as crosscuts multiple

classes and functions”

Page 26: Mixing functional and object oriented approaches to programming in C#

In the medium…

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

Page 27: Mixing functional and object oriented approaches to programming in C#

In the small…

“individual function/method bodies”

Page 28: Mixing functional and object oriented approaches to programming in C#

Large

Medium

Small

Page 29: Mixing functional and object oriented approaches to programming in C#

Large

Medium

Small

Page 30: Mixing functional and object oriented approaches to programming in C#

LINQ

Page 31: Mixing functional and object oriented approaches to programming in C#

a.k.a.Functional collection parameters

http://billsix.blogspot.com/2008/03/functional-collection-patterns-in-ruby.html

Page 32: Mixing functional and object oriented approaches to programming in C#

“powerful abstractions over collections”

Page 33: Mixing functional and object oriented approaches to programming in C#

“the use of high-order functions is extremely useful for separating the collection's concerns from the user

of the collection”

Page 34: Mixing functional and object oriented approaches to programming in C#

for loop becomes less useful

Page 35: Mixing functional and object oriented approaches to programming in C#

Don’t just use ForEach!

Page 36: Mixing functional and object oriented approaches to programming in C#

Code becomes more declarative

Page 37: Mixing functional and object oriented approaches to programming in C#

Declarative?

“a statement specifies some aspect of the desired answer with no notion of how that answer is to

be determined”

‘The Lush Landscape of Languages’ - The ThoughtWorks Anthology

Rebecca Parsons

Page 38: Mixing functional and object oriented approaches to programming in C#

Requires a mental shift from imperative thinking

Page 39: Mixing functional and object oriented approaches to programming in C#

Transformational mindset

Patrick Logan in the comments sectionhttp://www.markhneedham.com/blog/2010/01/20/functional-collectional-parameters-some-thoughts/

Page 40: Mixing functional and object oriented approaches to programming in C#

Current Input

???

???

???

Desired Output

Page 41: Mixing functional and object oriented approaches to programming in C#

Going from one collection to another

Page 42: Mixing functional and object oriented approaches to programming in C#

var words = new List<string> { “hello”, “world” };

var upperCaseWords = new List<string>();foreach (var word in words){

upperCaseWords.Add(word.ToUpper());}

Page 43: Mixing functional and object oriented approaches to programming in C#

a.k.a. map

QuickTime™ and a decompressor

are needed to see this picture.

Page 44: Mixing functional and object oriented approaches to programming in C#

“hello”, “world”

????

“HELLO”, “WORLD”

Page 45: Mixing functional and object oriented approaches to programming in C#

“hello”, “world”

Select

“HELLO”, “WORLD”

Page 46: Mixing functional and object oriented approaches to programming in C#

var words = new List<string> { “hello”, “world” };

var upperCaseWords = words.Select(w => w.ToUpper());

Page 47: Mixing functional and object oriented approaches to programming in C#

Remove values we don’t want

Page 48: Mixing functional and object oriented approaches to programming in C#

var words = new List<string> {“hello”, “world”};

var wordsWithH = new List<string>();foreach (var word in words){

if(word.Contains(“h”)wordsWithH.Add(word);

}

Page 49: Mixing functional and object oriented approaches to programming in C#

a.k.a. filter

QuickTime™ and a decompressor

are needed to see this picture.

Page 50: Mixing functional and object oriented approaches to programming in C#

“hello”, “world”

????

“hello”

Page 51: Mixing functional and object oriented approaches to programming in C#

“hello”, “world”

Where

“hello”

Page 52: Mixing functional and object oriented approaches to programming in C#

var words = new List<string> {“hello”, “world”} ;

var wordsWithH = words.Where(w => w.Contains(“h”));

Page 53: Mixing functional and object oriented approaches to programming in C#

Summing some values

Page 54: Mixing functional and object oriented approaches to programming in C#

var values = new List<int> { 1,2,3 };

var total = 0;foreach (var value in values){

total += value;}

Page 55: Mixing functional and object oriented approaches to programming in C#

a.k.a. reduce

QuickTime™ and a decompressor

are needed to see this picture.

Page 56: Mixing functional and object oriented approaches to programming in C#

1, 2, 3

???

6

Page 57: Mixing functional and object oriented approaches to programming in C#

1, 2, 3

Sum

6

Page 58: Mixing functional and object oriented approaches to programming in C#

var values = new List<int> { 1,2,3 };

var total = values.Sum(v => v);

Page 59: Mixing functional and object oriented approaches to programming in C#

Some examples from projects

Page 60: Mixing functional and object oriented approaches to programming in C#

Getting the first value that matches a criteria

Page 61: Mixing functional and object oriented approaches to programming in C#

Foo(“mark”, true), Foo(“dave”, false), Foo(“mike”, true)

????

Foo(“mark”, true)

Page 62: Mixing functional and object oriented approaches to programming in C#

Foo(“mark”, true), Foo(“dave”, false), Foo(“mike”, true)

Where

Foo(“mark”, true), Foo(“mike”, true)

???

Foo(“mark”, true)

Page 63: Mixing functional and object oriented approaches to programming in C#

Foo(“mark”, true), Foo(“dave”, false), Foo(“mike”, true)

Where

Foo(“mark”, true), Foo(“mike”, true)

First

Foo(“mark”, true)

Page 64: Mixing functional and object oriented approaches to programming in C#

var foos = new List<Foo> { new Foo(“mark”, true), new Foo(“dave”, false), new Foo(“mike”, true) };

var firstSpecialFoo = foos. Where(f => f.HasSpecialFlag()). First());

Page 65: Mixing functional and object oriented approaches to programming in C#

var foos = new List<Foo> { new Foo(“mark”, true), new Foo(“dave”, false), new Foo(“mike”, true) };

var firstSpecialFoo = foos.First(f => f.HasSpecialFlag());

Page 66: Mixing functional and object oriented approaches to programming in C#

Removing some columns from a dataset

Page 67: Mixing functional and object oriented approaches to programming in C#

a,b,c,d,e,f

????

“a,d,e,f”

Page 68: Mixing functional and object oriented approaches to programming in C#

a,b,c,d,e,f

Where

IEnumerable of a, d, e, f

???

“a,d,e,f”

Page 69: Mixing functional and object oriented approaches to programming in C#

a,b,c,d,e,f

Where

IEnumerable of a, d, e, f

???

String.Join on [a, d, e, f]

“a,d,e,f”

Page 70: Mixing functional and object oriented approaches to programming in C#

a,b,c,d,e,f

Where

IEnumerable of a, d, e, f

ToArray()

String.Join on [a, d, e, f]

“a,d,e,f”

Page 71: Mixing functional and object oriented approaches to programming in C#

var aRow = “a, b, c, d, e, f”;

var newRow = String.Join(“,”, aRow

.Split(‘,’) .Where((_, idx) => !(idx == 1 || idx == 2)) .ToArray());

Page 72: Mixing functional and object oriented approaches to programming in C#

var aRow = “a, b, c, d, e, f”;

var rowWithColumnsRemoved = aRow

.Split(‘,’) .Where((_, idx) => !(idx == 1 || idx == 2)) .ToArray());

var newRow = String.Join(“,”, rowWithColumnsRemoved);

Page 73: Mixing functional and object oriented approaches to programming in C#

Checking if any parameters are null

Page 74: Mixing functional and object oriented approaches to programming in C#

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 75: Mixing functional and object oriented approaches to programming in C#

public class SomeObject{ public SomeObject(string p1, string p2, string p3) { var params = new List<string> {p1, p2, p3}; if (params.Any(p => p == null) throw new Exception(...);

// rest of constructor logic }}

Page 76: Mixing functional and object oriented approaches to programming in C#

Some lessons from the wild

Page 77: Mixing functional and object oriented approaches to programming in C#

Dealing with the null collection

Page 78: Mixing functional and object oriented approaches to programming in C#

public int SumNumbers(List<int> list){if(list == null)

return 0;return list.Sum(v => v);

}

Page 79: Mixing functional and object oriented approaches to programming in C#

public IEnumerable<T> EmptyIfNull(this IEnumerable<T> collection)

{if(collection == null)

return new List<T>();return collection;

}

Chris Ammerman in the comments sectionhttp://www.markhneedham.com/blog/2009/06/16/functional-collection-

parameters-handling-the-null-collection/

Page 80: Mixing functional and object oriented approaches to programming in C#

public int SumNumbers(List<int> list){

return list.EmptyIfNull().Sum(v => v);

}

Page 81: Mixing functional and object oriented approaches to programming in C#

LINQ and the forgotten abstraction

Page 82: Mixing functional and object oriented approaches to programming in C#

Avoid passing lists around

Page 83: Mixing functional and object oriented approaches to programming in C#

public class Quote{public List<Coverage> Coverages {

get; set; }

}

Page 84: Mixing functional and object oriented approaches to programming in C#

Later on in the view…

Page 85: Mixing functional and object oriented approaches to programming in C#

<% var coverages = Model.Quote.Coverages; %>

<% if(coverages.Where(c => c.Name == “coverageType1”) %>

...

<% if(coverages.Where(c => c.Name == “coverageType2”) %>

...

<% if(coverages.Where(c => c.Name == “coverageType3”) %>

Page 86: Mixing functional and object oriented approaches to programming in C#

Objects as the mechanism for encapsulation

Page 87: Mixing functional and object oriented approaches to programming in C#

public class Coverages{

private readonly List<Coverage> coverages;

public Coverages(List<Coverage> coverages){

this.coverages = new List<Coverage>(coverages);}

public Coverage CoverageType1{ get {

return coverages.Where(c => c.Name == “coverageType1”;

}}

}

Page 88: Mixing functional and object oriented approaches to programming in C#

LINQ is duplication too!

Page 89: Mixing functional and object oriented approaches to programming in C#

public class Coverages{

public Coverage CoverageType1{ get {

return coverages.Where(c => c.Name == “coverageType1”;

}}

public Coverage CoverageType2{ get {

return coverages.Where(c => c.Name == “coverageType2”;

}}

}

Page 90: Mixing functional and object oriented approaches to programming in C#

public class Coverages{

public Coverage CoverageType1{

get { return CoverageByName(“coverageType1”); }

}

public Coverage CoverageType2{

get { return CoverageByName(“coverageType2”); }

}

public Coverage CoverageBy(string name){

return coverages.Where(c => c.Name == name);}

}

Page 91: Mixing functional and object oriented approaches to programming in C#

Don’t forget “extract method”

Page 92: Mixing functional and object oriented approaches to programming in C#

var someFoos = new List<Foo>()// put some foos in the list

someFoos.Select(f => new NewFoo {

Property1 = f.Property1...

});

Page 93: Mixing functional and object oriented approaches to programming in C#

var someFoos = new List<Foo>()// put some foos in the list

someFoos.Select(f => CreateNewFooFrom(f));

Page 94: Mixing functional and object oriented approaches to programming in C#

Naming lambda variables

Page 95: Mixing functional and object oriented approaches to programming in C#

Putting functions in maps

Page 96: Mixing functional and object oriented approaches to programming in C#

public void SomeMethodParsing(string input){

if (input == “input1”) {

someMethod(input);}else if (input == “input2”){

someOtherMethod(input);}// and so on

}

Page 97: Mixing functional and object oriented approaches to programming in C#

Dictionary<string, Action<string>> inputs = new Dictionary<string, Action<string>> { { “input1” , someMethod }, { “input2” , someOtherMethod } };

public void SomeMethodParsing(string input){

var method = inputs[input];method(input);

}

Page 98: Mixing functional and object oriented approaches to programming in C#

Large

Medium

Small

Page 99: Mixing functional and object oriented approaches to programming in C#

Using functions to simplify some GOF patterns

Page 100: Mixing functional and object oriented approaches to programming in C#

Action

Page 101: Mixing functional and object oriented approaches to programming in C#

Func

Page 102: Mixing functional and object oriented approaches to programming in C#

public class SomeObject{private readonly IStrategy strategy;

public Foo(IStrategy strategy){

this.strategy = strategy;}

public void DoSomething(string value){

strategy.DoSomething(value);}

}

Page 103: Mixing functional and object oriented approaches to programming in C#

public class Strategy : IStrategy{public void DoSomething(string value){

// do something with string}

}

Page 104: Mixing functional and object oriented approaches to programming in C#

public class SomeObject{private readonly Action<string> strategy;

public Foo(Action<string> strategy){

this. strategy = strategy;}

public void DoSomething(string value){

strategy(value);}

}

Page 105: Mixing functional and object oriented approaches to programming in C#

Need to ensure we don’t lose readability/understandability

Page 106: Mixing functional and object oriented approaches to programming in C#

The hole in the middle pattern

Brian Hurthttp://enfranchisedmind.com/blog/posts/the-hole-in-the-middle-pattern/

Page 107: Mixing functional and object oriented approaches to programming in C#

Common beginning and end.Only the middle differs

Page 108: Mixing functional and object oriented approaches to programming in C#

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 109: Mixing functional and object oriented approaches to programming in C#

public class CachedService : ServiceCache<IService>{

public MyResult GetMyResult(MyRequest request){

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

}}

Page 110: Mixing functional and object oriented approaches to programming in C#

Other ideas I’m intrigued about

Page 111: Mixing functional and object oriented approaches to programming in C#

The option type

Page 112: Mixing functional and object oriented approaches to programming in C#

The nested closure

Page 113: Mixing functional and object oriented approaches to programming in C#

File.open(“someFile.txt”, ‘w’) do |out|out << “add something to file”

end

Page 114: Mixing functional and object oriented approaches to programming in C#

public class MyFile { public static void Open(string filePath,

Action<StreamWriter> block) { using(var writer = new StreamWriter()) { block(writer ); } }}

Page 115: Mixing functional and object oriented approaches to programming in C#

MyFile.Open(“c:\\mark.txt”, f => f.WriteLine(“some random text”));

Page 116: Mixing functional and object oriented approaches to programming in C#

Writing extension methods to create functional abstractions

Page 117: Mixing functional and object oriented approaches to programming in C#

Learning more

Page 118: Mixing functional and object oriented approaches to programming in C#

QuickTime™ and a decompressor

are needed to see this picture.

Page 119: Mixing functional and object oriented approaches to programming in C#

3 things to take away

Page 120: Mixing functional and object oriented approaches to programming in C#

The transformational mindset

Page 121: Mixing functional and object oriented approaches to programming in C#

Objects are still the mechanism for encapsulation

Page 122: Mixing functional and object oriented approaches to programming in C#

Simplify GOF design patterns by using functions

Page 123: Mixing functional and object oriented approaches to programming in C#

Thanks to…

• Dave Cameron (not that one!) who I worked with on the structure and general content of the talk.

• Mike Wagg, Brian Blignaut, Chris Owen for reviewing the talk and giving their input.

Page 124: Mixing functional and object oriented approaches to programming in C#

Questions?

Mark Needham

http://www.markhneedham.com/blog/[email protected]: markhneedham