7 ineffective coding habits many f# programmers don't have

207
7 ineffective coding habits MANY F# programmers DON’T have

Upload: yan-cui

Post on 05-Jan-2017

91.734 views

Category:

Engineering


8 download

TRANSCRIPT

Page 1: 7 ineffective coding habits many F# programmers don't have

7 ineffectivecodinghabitsMANYF#programmersDON’Thave

Page 2: 7 ineffective coding habits many F# programmers don't have

BuildStuff ‘14

Page 3: 7 ineffective coding habits many F# programmers don't have
Page 4: 7 ineffective coding habits many F# programmers don't have

habitˈhabɪt/

A settled or regular tendency or practice, especially one that is hard to give up.

Page 5: 7 ineffective coding habits many F# programmers don't have

“I’m not a great programmer; I’m just a good programmer

with great habits.”

- Kent Beck

Page 6: 7 ineffective coding habits many F# programmers don't have

Noisy CodeVisual DishonestyLego NamingUnderabstractionUnencapsulated StateGetters and SettersUncohesive Tests

Page 7: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

does the language I use make a difference?

Page 8: 7 ineffective coding habits many F# programmers don't have

“Programming languages have a devious influence: they shape our thinking

habits.”

- Edsger W. Dijkstra

Page 9: 7 ineffective coding habits many F# programmers don't have

Noisy Code

Page 10: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 11: 7 ineffective coding habits many F# programmers don't have
Page 12: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 13: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

every LOC is a cost

Page 14: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

more code

more chance for bugs

Page 15: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

more code

more engineers

Page 16: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 17: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

You should do whatever possible to increase the productivity of individual programmers in terms of the expressive power of the code they write. Less code to do the same thing (and possibly better). Less programmers to hire. Less organizational communication costs.

Page 18: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

You should do whatever possible to increase the productivity of individual programmers in terms of the expressive power of the code they write. Less code to do the same thing (and possibly better). Less programmers to hire. Less organizational communication costs.

Page 19: 7 ineffective coding habits many F# programmers don't have

does the language I use make a difference?

Page 20: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 21: 7 ineffective coding habits many F# programmers don't have

@theburningmonksource http://bit.ly/1oBHHh1

Page 22: 7 ineffective coding habits many F# programmers don't have

@theburningmonksource http://bit.ly/1oBHHh1

Page 23: 7 ineffective coding habits many F# programmers don't have

@theburningmonksource http://bit.ly/1oBHHh1

Page 24: 7 ineffective coding habits many F# programmers don't have

@theburningmonksource http://bit.ly/1oBHHh1

Page 25: 7 ineffective coding habits many F# programmers don't have

@theburningmonksource http://bit.ly/1oBHHh1

Page 26: 7 ineffective coding habits many F# programmers don't have

@theburningmonksource http://bit.ly/1oBHHh1

Page 27: 7 ineffective coding habits many F# programmers don't have

@theburningmonksource http://bit.ly/1oBHHh1

Page 28: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Recap

Page 29: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

no { }no nulls

fewer syntactic noise

Page 30: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

fewer code

fewer noise

Page 31: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

fewer noise

higher SNR

Page 32: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

fewer code

more productivity

Page 33: 7 ineffective coding habits many F# programmers don't have

- Dan North

“Lead time to someone saying thank you is the only reputation

metric that matters.”

Page 34: 7 ineffective coding habits many F# programmers don't have

Visual Dishonesty

Page 35: 7 ineffective coding habits many F# programmers don't have

“…a clean design is one that supports visual thinking so

people can meet their informational needs with a

minimum of conscious effort.”

- Daniel Higginbotham (www.visualmess.com)

Page 36: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

public void MyCleverMethod( int firstArg, string secondArg)

signifies hierarchy

Page 37: 7 ineffective coding habits many F# programmers don't have

“You convey information by the way you arrange a design’s elements in relation to each other. This information is understood

immediately, if not consciously, by the people viewing your designs.”

- Daniel Higginbotham (www.visualmess.com)

Page 38: 7 ineffective coding habits many F# programmers don't have

“This is great if the visual relationships are obvious and accurate, but if they’re not, your audience is going to get confused.

They’ll have to examine your work carefully, going back and forth between the different

parts to make sure they understand.”

- Daniel Higginbotham (www.visualmess.com)

Page 39: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Whilst talking with an ex-colleague, a question came up on how to implement the Stable Marriage problem using a message passing approach. Naturally, I wanted to answer that question with Erlang!

Let’s first dissect the problem and decide what processes we need and how they need to interact with one another.

The stable marriage problem is commonly stated as:Given n men and n women, where each person has ranked all members of the opposite sex with a unique number between 1 and n in order of preference, marry the men and women together such that there are no two people of opposite sex who would both rather have each other than their current partners. If there are no such people, all the marriages are “stable”. (It is assumed that the participants are binary gendered and that marriages are not same-sex).From the problem description, we can see that we need:* a module for man* a module for woman* a module for orchestrating the experimentIn terms of interaction between the different modules, I imagined something along the lines of…

how we read ENGLISH

see also http://bit.ly/1KN8cd0

Page 40: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Whilst talking with an ex-colleague, a question came up on how to implement the Stable Marriage problem using a message passing approach. Naturally, I wanted to answer that question with Erlang!

Let’s first dissect the problem and decide what processes we need and how they need to interact with one another.

The stable marriage problem is commonly stated as:Given n men and n women, where each person has ranked all members of the opposite sex with a unique number between 1 and n in order of preference, marry the men and women together such that there are no two people of opposite sex who would both rather have each other than their current partners. If there are no such people, all the marriages are “stable”. (It is assumed that the participants are binary gendered and that marriages are not same-sex).From the problem description, we can see that we need:* a module for man* a module for woman* a module for orchestrating the experimentIn terms of interaction between the different modules, I imagined something along the lines of…

2. top-to-bottom1.left-to-right

how we read ENGLISH

see also http://bit.ly/1KN8cd0

Page 41: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

how we read CODE

public void DoSomething(int x, int y){ Foo(y, Bar(x, Zoo(Monkey())));}

see also http://bit.ly/1KN8cd0

Page 42: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

how we read CODE

public void DoSomething(int x, int y){ Foo(y, Bar(x, Zoo(Monkey())));}

2. bottom-to-top

1.right-to-left

see also http://bit.ly/1KN8cd0

Page 43: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Whilst talking with an ex-colleague, a question came up on how to implement the Stable Marriage problem using a message passing approach. Naturally, I wanted to answer that question with Erlang!

Let’s first dissect the problem and decide what processes we need and how they need to interact with one another.

The stable marriage problem is commonly stated as:Given n men and n women, where each person has ranked all members of the opposite sex with a unique number between 1 and n in order of preference, marry the men and women together such that there are no two people of opposite sex who would both rather have each other than their current partners. If there are no such people, all the marriages are “stable”. (It is assumed that the participants are binary gendered and that marriages are not same-sex).From the problem description, we can see that we need:* a module for man* a module for woman* a module for orchestrating the experimentIn terms of interaction between the different modules, I imagined something along the lines of…

2. top-to-bottom

1.left-to-right

how we read ENGLISH

public void DoSomething(int x, int y){ Foo(y, Bar(x, Zoo(Monkey())));}

2. top-to-bottom

1.right-to-left

how we read CODE

see also http://bit.ly/1KN8cd0

Page 44: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

|>see also http://bit.ly/1KN8cd0

Page 45: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

how we read CODE

let drawCircle x y radius = circle radius |> filled (rgb 150 170 150) |> alpha 0.5 |> move (x, y)

see also http://bit.ly/1KN8cd0

Page 46: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

how we read CODE

let drawCircle x y radius = circle radius |> filled (rgb 150 170 150) |> alpha 0.5 |> move (x, y)

2. top-to-bottom1.left-to-right

see also http://bit.ly/1KN8cd0

Page 47: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

{}

Page 48: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

public ResultType MyCleverMethod( int firstArg, string secondArg, string thirdArg) { var localVar = AnotherCleverMethod(firstArg, secondArg); if (localVar.IsSomething( thirdArg, MY_CONSTANT)) { DoSomething(localVar); } return localVar.GetSomething();}

Page 49: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

XXXXXX XXXXXXXXXX XXXXXXXXXXXXXX XXX XXXXXXXX XXXXXX XXXXXXXXX XXXXXX XXXXXXXX XXX XXXXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXX XXXXXXXXX XX XXXXXXXX XXXXXXXXXXX XXXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXXXXX XXXXXX XXXXXXXX XXXXXXXXXXXX

Page 50: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

public ResultType MyCleverMethod( int firstArg, string secondArg, string thirdArg) { var localVar = AnotherCleverMethod(firstArg, secondArg); if (localVar.IsSomething( thirdArg, MY_CONSTANT)) { DoSomething(localVar); } return localVar.GetSomething();}

Page 51: 7 ineffective coding habits many F# programmers don't have

“This is great if the visual relationships are obvious and accurate, but if they’re not, your audience is going to get confused.

They’ll have to examine your work carefully, going back and forth between the different

parts to make sure they understand.”

Page 52: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

public ResultType MyCleverMethod( int firstArg, string secondArg, string thirdArg) { var localVar = AnotherCleverMethod(firstArg, secondArg); if (localVar.IsSomething( thirdArg, MY_CONSTANT)) { DoSomething(localVar); } return localVar.GetSomething();}

Page 53: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

XXXXXX XXXXXXXXXX XXXXXXXXXXXXXX XXX XXXXXXXX XXXXXX XXXXXXXXX XXXXXX XXXXXXXX

XXX XXXXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXX XXXXXXXXX XX XXXXXXXX XXXXXXXXXXX XXXXXXXX XXXXXXXXXX

XXXXXXXXXXX XXXXXXXX XXXXXX XXXXXXXX XXXXXXXXXXXX

Page 54: 7 ineffective coding habits many F# programmers don't have

- Douglas Crockford

“It turns out that style matters in programming for

the same reason that it matters in writing.

It makes for better reading.”

Page 55: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

two competing rules for structuring code in C-style languages

Page 56: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Compiler

{ }

Human

{ } + whitespace

Page 57: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

what if…?

Page 58: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Compiler

whitespace

Human

whitespace

Page 59: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

xxx {}

xxx {}

no braces no

problem

Page 60: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

There should be one - and preferably only one - obvious way to do it.

- the Zen of Python

Page 61: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

let myCleverFunction x y z = let localVar = anotherCleverFunction x y

if localVar.IsSomething(z, MY_CONSTANT) then doSomething localVar localVar.GetSomething()

Page 62: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

XXX XXXXXXXXXXXXXXXX X X X XXX XXXXXXXX XXXXXXXXXXXXXXXXXXXX X X

XX XXXXXXXX XXXXXXXXXXX X XXXXXXXXXX XXXX XXXXXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXXXXXX

Page 63: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

You should do whatever possible to increase the productivity of individual programmers in terms of the expressive power of the code they write. Less code to do the same thing (and possibly better). Less programmers to hire. Less organizational communication costs.

Page 64: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Recap

Page 65: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

|>

Page 66: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

one way to describe hierarchy

Page 67: 7 ineffective coding habits many F# programmers don't have

Lego Naming

Page 68: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

naming is HARD

Page 69: 7 ineffective coding habits many F# programmers don't have

- Phil Karlton

“There are only two hard things in Computer Science: cache

invalidation and naming things.”

Page 70: 7 ineffective coding habits many F# programmers don't have

- Mike Mahemoff

“Names are the one and only tool you have to explain what a variable does in every place it

appears, without having to scatter comments everywhere.”

Page 71: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Lego NamingGluing common words together in an

attempt to create meaning.

Page 72: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Strategy

Process

Create

Add

Controller

Factory

Proxy

ObjectException

Enable

Do

Disable

Service

RemoveCheck

GetSet

Update

Validate

Page 73: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

see http://methodnamer.com

Page 74: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

this is not naming

Page 75: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

this is not namingthis is labelling

Page 76: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 77: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 78: 7 ineffective coding habits many F# programmers don't have
Page 79: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

naming is HARD

Page 80: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

anonymous functionsaka lambdas

Page 81: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

fewer things to name

Page 82: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

words |> Array.map (fun x -> x.Count) |> Array.reduce (+)

Page 83: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

smaller scopeshorter names

Page 84: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 85: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

http://bit.ly/1ZpAByu

When x, y, and z are great variable names

Page 86: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

"The length of a name should be related to the length of the scope. You can use very short variable names for tiny scopes, but for big

scopes you should use longer names.

Variable names like i and j are just fine if their scope is five lines long."

- Robert C. Martin

Page 87: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

object expressions

Page 88: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

enterpriseCrew.OrderBy( (fun c -> c.Current), { new IComparer<Occupation> with

member this.Compare(x, y) = x.Position.CompareTo(y.Position) })

Page 89: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

enterpriseCrew.OrderBy( (fun c -> c.Current), { new IComparer<Occupation> with

member this.Compare(x, y) = x.Position.CompareTo(y.Position) })

Page 90: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

fewer things to name

Page 91: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

tuples + pattern matching

Page 92: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

tuples + pattern matching

fewer abstractions

Page 93: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

tuples + pattern matching

fewer abstractions

fewer things to name

Page 94: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

words |> Seq.groupBy id |> Seq.map (fun (word, gr) -> word, Seq.length gr) |> Seq.iter (fun (word, len) -> printfn “%s - %s” word len)

Page 95: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

words |> Seq.groupBy id |> Seq.map (fun (word, gr) -> word, Seq.length gr) |> Seq.iter (fun (word, len) -> printfn “%s - %s” word len)

Page 96: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

words |> Seq.groupBy id |> Seq.map (fun (word, gr) -> word, Seq.length gr) |> Seq.iter (fun (word, len) -> printfn “%s - %s” word len)

Page 97: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

words |> Seq.groupBy id |> Seq.map (fun (word, gr) -> word, Seq.length gr) |> Seq.iter (fun (word, len) -> printfn “%s - %s” word len)

Page 98: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Lego Naming can also be the symptom of a failure to

identify the right level of abstractions.

Page 99: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

the RIGHT level of abstraction might be smaller than “object”

Page 100: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

public interface ConditionChecker{ bool CheckCondition();}

Page 101: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

public interface Condition{ bool IsTrue();}

Page 102: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 103: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

type Condition = unit -> bool

Page 104: 7 ineffective coding habits many F# programmers don't have

source https://vimeo.com/113588389

Page 105: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

ClassNotFoundException IllegalArgumentException IndexOutOfBoundsException NoSuchMethodException UnsupportedOperationException

Page 106: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

ClassNotFound IllegalArgument IndexOutOfBounds NoSuchMethod UnsupportedOperation

Page 107: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

ArithmeticException ArrayStoreException ClassCastException InstantiationException NullPointerException SecurityException

Page 108: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

IntegerDivisionByZero IllegalArrayElementType CastToNonSubclass ClassCannotBeInstantiated NullDereferenced SecurityViolation

Page 109: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

lightweight exception syntax

Page 110: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

open System open System.IO

exception InsufficientBytes

Page 111: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

open System open System.IO

exception InsufficientBytes

what could this type represent?

Page 112: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Recap

Page 113: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

F# < > silver bullet

Page 114: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

anonymous functions

fewer things to name

Page 115: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

short names

Page 116: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

tuple + pattern matching

fewer things to name

Page 117: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

no abstraction is too small

Page 118: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

lightweight exception syntax

Page 119: 7 ineffective coding habits many F# programmers don't have

Underabstraction

Page 120: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 121: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

public Result DoSomething( int a, string b, string c, string d, DateTime e, DateTime f, string g, MyEnum h)

Page 122: 7 ineffective coding habits many F# programmers don't have

“If you have a procedure with ten parameters, you probably missed some.”

- Alan Perlis

Page 123: 7 ineffective coding habits many F# programmers don't have

source https://vimeo.com/97507575

Page 124: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

lightweight syntax for types and hierarchies

Page 125: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

record

Page 126: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

type Employee = { FirstName : string Surname : string Salary : int<Pound> }

Page 127: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

type Employee = { FirstName : string Surname : string Salary : int<Pound> } immutable by default

Page 128: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

let promote emp raise = { emp with Salary <- emp.Salary + raise }

Page 129: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

mutable state complects

value and time

Page 130: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

type Employee = { FirstName : string Surname : string Salary : int<Pound> } unit-of-measure

Page 131: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

[<Measure>]type Pound

e.g. 42<Pound> 153<Pound>

Page 132: 7 ineffective coding habits many F# programmers don't have

10<Meter> / 2<Second> = 5<Meter/Second>10<Meter> * 2<Second> = 20<Meter Second> 10<Meter> + 10<Meter> = 20<Meter>10<Meter> * 10 = 100<Meter>10<Meter> * 10<Meter> = 100<Meter2>10<Meter> + 2<Second> // error10<Meter> + 2 // error

Page 133: 7 ineffective coding habits many F# programmers don't have

10<Meter> / 2<Second> = 5<Meter/Second>10<Meter> * 2<Second> = 20<Meter Second> 10<Meter> + 10<Meter> = 20<Meter>10<Meter> * 10 = 100<Meter>10<Meter> * 10<Meter> = 100<Meter2>10<Meter> + 2<Second> // error10<Meter> + 2 // error

Page 134: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

discriminated unions

Page 135: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

type PaymentMethod = | Cash | Cheque of ChequeNumber | Card of CardType * CardNumber

Page 136: 7 ineffective coding habits many F# programmers don't have

Unencapsulated State

Page 137: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 138: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

public class RecentlyUsedList { private List<string> items = new List<string>(); public List<string> Items { get { return items; } }

… }

Page 139: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

immutability

Page 140: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

type RecentlyUsedList (?items) = let items = defaultArg items [ ]

member this.Items = Array.ofList items

member this.Count = List.length items

member this.Add newItem = newItem::(items |> List.filter ((<>) newItem)) |> RecentlyUsedList

Page 141: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Affordancean affordance is a quality of an object, or

an environment, which allows an individual to perform an action. For example, a knob

affords twisting, and perhaps pushing, whilst a cord affords pulling.

Page 142: 7 ineffective coding habits many F# programmers don't have

source https://www.youtube.com/watch?v=aAb7hSCtvGw

Page 143: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

your abstractions should afford right behaviour,

whilst make it impossible to do the wrong thing

Page 144: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

“Make illegal states unrepresentable”

- Yaron Minsky

Page 145: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

discriminated unions

Page 146: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

type PaymentMethod = | Cash | Cheque of ChequeNumber | Card of CardType * CardNumber

finite, closed set of valid states ONLY

Page 147: 7 ineffective coding habits many F# programmers don't have

closed hierarchy

Page 148: 7 ineffective coding habits many F# programmers don't have

no Nulls

Page 149: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

match paymentMethod with | Cash -> … | Cheque chequeNum -> … | Card (cardType, cardNum) -> …

Page 150: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Recap

Page 151: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

immutability

Page 152: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

make illegal state unrepresentable

Page 153: 7 ineffective coding habits many F# programmers don't have

Getters and Setters

Page 154: 7 ineffective coding habits many F# programmers don't have

“When it’s not necessary to change, it’s necessary to not change.”

- Lucius Cary

Page 155: 7 ineffective coding habits many F# programmers don't have

“Now we have shortcuts to do the wrong thing.

We used to have type lots to do the wrong thing, not anymore.”

- Kevlin Henney

Page 156: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

immutability by default

Page 157: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

type Person = { Name : string Age : int }

Page 158: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

type Person = { mutable Name : string mutable Age : int }

Page 159: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

immutability

Page 160: 7 ineffective coding habits many F# programmers don't have

Uncohesive Tests

Page 161: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

MethodA

MethodB

When_…Then_… ()When_…Then_… ()When_…Then_… ()When_…Then_… ()When_…Then_… ()When_…Then_… ()

Page 162: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

MethodA

MethodB

MethodC

FeatureA

FeatureB

Page 163: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

complexities & potential bugs in the way methods

work together

Page 164: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

…especially when states are concerned

Page 165: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Test Driven Development

Page 166: 7 ineffective coding habits many F# programmers don't have

“For tests to drive development they must do more than just test that code

performs its required functionality: they must clearly express that required

functionality to the reader. That is, they must be clear specification of the

required functionality.”

- Nat Pryce & Steve Freeman

Page 167: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 168: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

how many tests?

Page 169: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

every test has a cost

Page 170: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

did we cover all the edge cases?

Page 171: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Property-Based Testing(with FsCheck)

Page 172: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

List.rev

reverse + reverse = originallength of list is invariantappend + reverse = reverse + prepend

Page 173: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

List.revproperty : reverse + reverse = original

let ``reverse + reverse = original`` rev aList = aList |> rev |> rev = aList

Check.Quick (``reverse + reverse = original`` List.rev) // Ok, passed 100 tests.

Page 174: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

List.revproperty : length of list is invariant

let ``length of list is invariant`` rev aList = List.length (rev aList) = List.length aList

Check.Quick (``length of list is invariant`` List.rev) // Ok, passed 100 tests.

Page 175: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

List.revproperty : append + reverse = reverse + prepend

let ``append + reverse = reverse + prepend`` rev x aList = (aList @ [x]) |> rev = x::(aList |> rev)

Check.Quick (``append + reverse = reverse + prepend`` List.rev) // Ok, passed 100 tests.

Page 176: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Check.Verbose (``append + reverse = reverse + prepend`` List.rev) // 0: ‘\005' [] 1: false ["N "] 2: “" [false; '{'] 3: ‘\017' [true; true; 'W'] 4: “" [""; false] 5: “yg]" [“H\nOq6"; null; false; false; '#'] 6: true [“"] … 11: <null> ['\014'; '0'; “\nRH”; "<#oe"; true; false; ‘O'] …

Page 177: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

shrinking

Page 178: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Check.Quick (``append + reverse = reverse + prepend`` id) // Falsifiable, after 2 tests (4 shrinks) (StdGen (1855582125,296080469)):

Original:‘\013' ["}k"; ""; “"]

Shrunk:true [false]

Page 179: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

let computers do the grunt work

Page 180: 7 ineffective coding habits many F# programmers don't have

source : http://bit.ly/1kEpEso

Page 181: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Types vs Tests

Page 182: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

all bugs

Page 183: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

unknown

known

Page 184: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

tests

types

Page 185: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

tests

types

Page 186: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

unit-testing

distr. systemssystem-testing

Page 187: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Jepsenproperty-based

unit-testing system-testing

distr. systems

Page 188: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Jepsenproperty-based

unit-testing

types as proof TLA+

distr. systemssystem-testing

Page 189: 7 ineffective coding habits many F# programmers don't have

Noisy CodeVisual DishonestyLego NamingUnderabstractionUnencapsulated StateGetters and SettersUncohesive Tests

Page 190: 7 ineffective coding habits many F# programmers don't have

“Practice does not make perfect.Only perfect practice makes perfect.”

- Vince Lombardi

Page 191: 7 ineffective coding habits many F# programmers don't have

“Perfection is not attainable. But if we chase perfection, we can catch excellence.”

- Vince Lombardi

Page 192: 7 ineffective coding habits many F# programmers don't have

“Programming languages have a devious influence: they shape our thinking

habits.”

- Edsger W. Dijkstra

Page 193: 7 ineffective coding habits many F# programmers don't have

“One of the most disastrous thing we can learn is the first programming language, even

if it's a good programming language.”

- Alan Kay

Page 194: 7 ineffective coding habits many F# programmers don't have

“I’m not a great programmer; I’m just a good programmer

with great habits.”

- Kent Beck

Page 195: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

what about ineffective coding habits SOME F#/FP

programmers DO have?

Page 196: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 197: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

people are too puritanical about purity

Page 198: 7 ineffective coding habits many F# programmers don't have

…premature optimization is the root of all evil. Yet we should not pass up our opportunities in that

critical 3%

- Donald Knuth

Page 199: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

F# Map vs .Net array vs Dictionary

Page 200: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Page 201: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Explicit is better than implicit.

- the Zen of Python

Page 202: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Simple is better than Complex.Complex is better than Complicated.

- the Zen of Python

Page 203: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Special cases aren't special enough to break the rules.

- the Zen of Python

Page 204: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

Special cases aren't special enough to break the rules.

Although practicality beats purity.

- the Zen of Python

Page 205: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

If the implementation is hard to explain, it's a bad idea.

- the Zen of Python

Page 206: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

@theburningmonktheburningmonk.comgithub.com/theburningmonk

Page 207: 7 ineffective coding habits many F# programmers don't have

@theburningmonk

is hiring :-)http://tech.just-eat.com/jobs