functional programming with c#

Post on 20-Jan-2017

105 Views

Category:

Software

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Functional Programming in C#

What is Functional Programming?

• Side-effect free programming?• Higher order functions?• Use of a functional language like F# / Haskell / Scala?

Functional programming is programming with mathematical

functions.

Problem solved!

What is Functional Programming?

Mathematicalfunction

Class method=

What is Functional Programming?

fReferential transparency: same input – same result

Information about possible inputs and outcomes

What is Functional Programming?

public double Calculate(double x, double y){ return x * x + y * y;}

public long TicksElapsedFrom(int year){ DateTime now = DateTime.Now; DateTime then = new DateTime(year, 1, 1);

return (now - then).Ticks;}

Same input – same result Result is always different

What is Functional Programming?

public static int Divide(int x, int y){ return x / y;}

fInteger

IntegerInteger

1

0

?

DivideByZeroException

Method Signature Honesty

Method signature

All possible inputs

All possible outcomes

Method Signature Honesty

Honest signatureDishonest signature

public static int Divide(int x, int y){ return x / y;}

public static int Divide(int x, NonZeroInteger y){ return x / y.Value;}public static int? Divide(int x, int y){ if (y == 0) return null;

return x / y;}

Mathematical Function

• Honest• Has precisely defined input and output

• Referentially transparent• Doesn’t affect or refer to the global state

Why Functional Programming?

Composable

Easy to reason about

Easier to unit test

Reducing complexity

Immutability

• Immutability• Inability to change data

• State• Data that changes over time

• Side effect• A change that is made to some state

Immutability

Mutable operations

Dishonest code=

Immutability

fInput Output

Side effect

Method signature

Hidden part

Immutability

fInputOutput

Side effect

Method signature

Hidden part

Output 2

Why Does Immutability Matter?

• Increased readability• A single place for validating invariants• Automatic thread safety

How to Deal with Side Effects

Command–query separation principle

Command Query

Produces side effects Side-effect free

Returns void Returns non-void

How to Deal with Side Effects

public class CustomerService { public void Process(string customerName, string addressString) { Address address = CreateAddress(addressString); Customer customer = CreateCustomer(customerName, address); SaveCustomer(customer); }

private Address CreateAddress(string addressString) { return new Address(addressString); }

private Customer CreateCustomer(string name, Address address) { return new Customer(name, address); }

private void SaveCustomer(Customer customer) { var repository = new Repository(); repository.Save(customer); }}

Command

Query

Command

Query

How to Deal with Side Effects

var stack = new Stack<string>();stack.Push("value"); // Commandstring value = stack.Pop(); // Both query and command

How to Deal with Side Effects

Application

Domain logic Mutating state

Generates artifacts Uses artifacts to change the system’s state

How to Deal with Side Effects

Immutable CoreInput Artifacts

Mutable Shell

Exceptions and Readability

public ActionResult CreateEmployee(string name) { try { ValidateName(name); // Rest of the method

return View("Success"); } catch (ValidationException ex) { return View("Error", ex.Message); }}

private void ValidateName(string name) { if (string.IsNullOrWhiteSpace(name)) throw new ValidationException("Name cannot be empty");

if (name.Length > 100) throw new ValidationException("Name is too long");}

Exceptions and Readability

public Employee CreateEmployee(string name){ ValidateName(name);

// Rest of the method}

Exceptions and Readability

Exceptions for flow control

Goto statements=

Exceptions and Readability

Method with exceptions

Mathematical function=

Exceptions and Readability

fInput Output

Exceptions

Method signature

Hidden part

Always prefer return values over exceptions.

Use Cases for Exceptions

• Exceptions are for exceptional situations• Exceptions should signalize a bug• Don’t use exceptions in situations you expect to happen

Use Cases for Exceptions

Validations Exceptional situation=

Primitive Obsession

Primitive obsession stands for using primitive types for

domain modeling.

Drawbacks of Primitive Obsession

public class User{ public string Email { get; }

public User(string email) { Email = email; }}

public class User{ public string Email { get; }

public User(string email) { if (string.IsNullOrWhiteSpace(email)) throw new ArgumentException("Email should not be empty");

email = email.Trim(); if (email.Length > 256) throw new ArgumentException("Email is too long");

if (!email.Contains("@")) throw new ArgumentException("Email is invalid");

Email = email; }}

Drawbacks of Primitive Obsession

Drawbacks of Primitive Obsession

public class Organization{ public string PrimaryEmail { get; }

public Organization(string primaryEmail) { PrimaryEmail = primaryEmail; }}

public class Organization{ public string PrimaryEmail { get; }

public Organization(string primaryEmail) { if (string.IsNullOrWhiteSpace(primaryEmail)) throw new ArgumentException("Email should not be empty");

primaryEmail = primaryEmail.Trim(); if (primaryEmail.Length > 256) throw new ArgumentException("Email is too long");

if (!primaryEmail.Contains("@")) throw new ArgumentException("Email is invalid");

PrimaryEmail = primaryEmail; }}

Drawbacks of Primitive Obsession

Drawbacks of Primitive Obsession

Dishonest signature

public class UserFactory{ public User CreateUser(string email) { return new User(email); }}

public int Divide(int x, int y){ return x / y;}

fstring user

Dishonest signature

Drawbacks of Primitive Obsession

Makes code dishonest

Violates the DRY principle

Wrap primitive types with separate classes

Drawbacks of Primitive Obsession

public class UserFactory{ public User CreateUser(Email email) { return new User(email); }}

public int Divide(int x, NonZeroInteger y){ return x / y;}

femail user

Honest signature Honest signature

Getting Rid of Primitive Obsession

• Removing duplications• Method signature honesty• Stronger type system

The Billion-dollar Mistake

string someString = null;Customer customer = null;Employee employee = null;

The Billion-dollar Mistake

“I call it my billion-dollar mistake. It has caused a billion dollars of pain and damage in the last forty years.”

Tony Hoare

The Billion-dollar Mistake

public class Organization{ public Employee GetEmployee(string name) { /* ... */ }}

public class OrganizationRepository{ public Organization GetById(int id) { /* ... */ }}

The Billion-dollar Mistake

public class MyClassOrNull{ // either null public readonly Null Null; // or actually a MyClass instance public readonly MyClass MyClass; }

public class MyClass{}

The Billion-dollar Mistake

fInteger MyClass

MyClassOrNull

Dishonest

Mitigating the Billion-dollar Mistake

Maybe<T>

Mitigating the Billion-dollar Mistake

public class OrganizationRepository{

public Organization GetById(int id) { /* ... */ }}

Maybe<Organization>

Mitigating the Billion-dollar Mistake

public class OrganizationRepository{ public Maybe<Organization> GetById(int id) { /* ... */ }}

public class Organization{ public Employee GetEmployee(string name) { /* ... */ }}

Mitigating the Billion-dollar Mistake

public class OrganizationRepository{ public Maybe<Organization> GetById(int id) { /* ... */ }}

public static int? Divide(int x, int y){ if (y == 0) return null;

return x / y;}

Honest

Honest

Functional C#

Demo time

Summary

• Functional programming is programming with mathematical functions• Method signature honesty• Referential transparency

• Side effects and exceptions make your code dishonest about the outcome it may produce

• Primitive obsession makes your code dishonest about its input parts

• Nulls make your code dishonest about both its inputs and outputs• Applying Functional Principles in C# Pluralsight course:

https://app.pluralsight.com/courses/csharp-applying-functional-principles

THANK YOU

Vladimir Khorikov @vkhorikovvkhorikov@eastbanctech.com202-295-3000eastbanctech.com

top related